MODULE Fred;

(*==============================================================*
 * Modul:               Fred - der Editor Main Modul            *
 * Autor:               Dirk Steins                             *
 * erstellt am:         4.11.1991                               *
 * letzte Žnderung am:  17.4.1994                               *
 * Version:             0.91                                    *
 * Interne Version:     V#0089                                  *
 *==============================================================*

 *----------------------------------------------------------------------------
 * Datum    Vers. Autor Žnderung (Arbeitsbericht)                            
 *----------------------------------------------------------------------------
 * 4.11.91  0.1   DS    Modul erstellt                                                                      
 *
 * 8.4.92   0.35  DS    umgestellt auf neue Window-Library
 * 18.4.95  0.91  DS    angepažt an CAT_GOLD-Sourcen
 * 5.6.95   0.92  DS    neu compiliert mit aktuelleren Sourcen
 *----------------------------------------------------------------------------
 *)

(* F�r Fehlerbehandlung unter der Shell: *)
FROM PrgCtrl            IMPORT CatchProcessTerm, TermCarrier, TermProcess;
FROM MOSGlobals         IMPORT MemArea;
IMPORT MOSCtrl;

(*IMPORT GEMDOSIO;
IMPORT InOut; *)
FROM SYSTEM             IMPORT ADDRESS, ADR, CODE, CADR, ASSEMBLER, TSIZE;
FROM Storage            IMPORT ALLOCATE, DEALLOCATE, MemAvail;

(* MM2-spezifische Libs! *)
FROM Characters         IMPORT CR, LF;

IMPORT  StrConv,
        Strings,        (* String-Operationen *)
        Paths,          (* Pfadliste          *)
        ShellMsg,       (* Variablen der Shell*)
        Lists,          (* F�r Listenooperationen auf den Pfadlisten *)
        FileNames;      (* String-Operationen auf Dateinamen *)

(* Magic-Module *)
IMPORT MagicAES;
IMPORT MagicVDI;
IMPORT MagicDOS;
IMPORT MagicXBIOS;
IMPORT MagicCookie;
IMPORT mtAppl;
IMPORT mtCommand;
IMPORT mtUtils;
IMPORT mtDials;
IMPORT mtDir;
IMPORT mtAlerts;
IMPORT mtPopups;
IMPORT mtTime;
IMPORT mtTextfiles;
IMPORT MagicSys;
IMPORT MagicStrings;
IMPORT MagicConvert;

IMPORT MintUtil;
IMPORT Mintbind;

(* CAT-Module *)
IMPORT  CatTypes,       (* Ein paar Typ-Definitionen    *)
        CatEdit,        (* Der eigentliche Editor :-)   *)
        EditFuncs,      (* Noch ein paar Funktionen     *)
        EditTypes;      (* Typen f�r den Editor         *)
IMPORT WdwManager;      (* Window-Library               *)
IMPORT FontSelect;
IMPORT CatFiles;
IMPORT Printer;

FROM Void               IMPORT v;
FROM SearchMenu         IMPORT MenuSearch;
FROM SwapServer         IMPORT SplitWordToByte, SmallerCard;
IMPORT ShellCall;

FROM CatGlobal           IMPORT FselGet;
IMPORT CatGlobal;

IMPORT Varnames;
IMPORT ConfVars;
IMPORT AssFuncs;
IMPORT Find2;
IMPORT WinDials;

(* FRED-Module *)
IMPORT WildCards;
IMPORT PListHelp;
FROM FredProtokoll      IMPORT IsProtokoll, React, SendTerminate, 
                               SendOpenwind, SendHelp, ProtoInit,
                               SeProtoInit, SendEsMessage,
                               SEProtoActiv;
IMPORT SEProto;
(* Resource Definitions *)

IMPORT Fredrsc;

CONST   pVersion        = ' 0.96 ž';

        pDate           = '26.10.1997';

        eddixName       = '  Fred'+pVersion+0C;

        sysStrOne       = 'Shell aufrufen';
        blockSaveAs     = 'Block sichern als...';
        saveAs          = 'Sichern als...';
        
        wrongWildAlert  = '[2][FRED:|Die Wildcardzeichen sind|nicht korrekt!|Bitte korrigierenm Sie|Ihre Eingaben!][[OK]';
        wrongWildReplace  = '[3][FRED:|Die Zuordnung der Wildcards|ist nicht eindeutig!][[Abbruch]';
        noSearchStr     = "[3][FRED:|Fehler im Suchmuster!|Suchstrings, die nur aus|Wildcardzeichen bestehen,|sind nicht erlaubt!][[Nochmal]";
        NoWinDial       = "[3][FRED:|Es ist kein Fenster|f�r den Dialog verf�gbar!|Bitte schliežen sie ein|anderes Fenster.][[OK]";
        
        cfgNotFound     = '[3][FRED:|CFG-File nicht|gefunden!][[Abbruch]';
        noCfgFile       = '[3][FRED:|Diese Datei ist|keine CFG-Datei!][[Abbruch]';
        
        maxLineLength   = 4096;

        magicPCCookie = 'MgPC';

CONST whatString = '@(#)Fred '+pVersion + ', Copyright (c) 1997 Dirk Steins (Oct 26 1997)'+0C;

    (* Variablennamen f�r CFG-File *)
    cErrExtension   = 'ErrorExtension';
    cErrMask        = 'ErrorMask';
    cHelpLine       = 'HelpLineLayout';
    cPrjExtension   = 'ProjectExtension';
    (*
    cExtension      = 'Extension';
    cExtTabsize     = 'ExtTabSize';
    cExtHardTabs    = 'ExtHardTabs';
    cExtWordWrap    = 'ExtWordWrap';
    cExtRightMargin = 'ExtRightMargin';
    cExtAutoBackup  = 'ExtAutoBackup';
    *)
    cSourcePath     = 'SourcePath';
    cNormalFkey     = 'NormalF';
    cAutoSavePrefs  = 'AutoSavePrefs';
    cShortFile      = 'LastShortcutFile';
 
TYPE magixCookiePtr = POINTER TO magixRecord;
     magixRecord    = RECORD
                        confStatus : LONGCARD;
                        dosVars    : ADDRESS;
                        aesVars    : ADDRESS;
                      END;
CONST
     allWild    = '*.*';

CONST   maxErrFiles = 4;

TYPE    listRecord  = RECORD
                        wdw : INTEGER;
                        fname: CatTypes.String255;
                      END;
        errorArray  = ARRAY [0..maxErrFiles-1] OF listRecord;


VAR     errIndex: INTEGER;
        errFiles: errorArray;
        errMask : CatTypes.String255;

TYPE CharSet    = SET OF CHAR;
     
     MaxStr     = ARRAY [0..255] OF CHAR;
     PtrMaxStr  = POINTER TO MaxStr;


(* Wirklich benutzte Variable: *)

VAR
        InSel           : ARRAY[0..40] OF CHAR;
        SaveName        : ARRAY[0..40] OF CHAR;

        SCAN            : INTEGER;
        CH              : CHAR;
        moButton        : BITSET;
        kReturn         : INTEGER;
        moKState        : BITSET;
        moX, moY        : INTEGER;
        bReturn         : INTEGER;
        event           : BITSET;
        e               : BITSET;
        scan,                   
        char            : CHAR; 
        null            : RECORD d1,d2 : LONGCARD END;
        mess,
        mScrap          : ARRAY[0..7] OF INTEGER;

        dr, mrect       : RECORD
                            CASE :BOOLEAN OF
                              TRUE : x,y,w,h : INTEGER|
                              FALSE: adr, dum: ADDRESS
                            END
                          END;
        mouse           : BOOLEAN;

        apId            : CARDINAL;
        devHdl          : INTEGER;

        (* Adressen der Objektb„ume *)        
        menu            : ADDRESS;
        infoBox,
        aboutBox,
        lineBox,
        tabBox,
        umbruchBox,
        floskelBox,
        gotoBox,
        systemBox,
        pathBox,
        fredIcon,
        shortBox,
        errorBox,
        suchBox         : ADDRESS;

        (* Pfade *)        
        homePath        : MaxStr;
        InPath          : MaxStr;
        SavePath        : MaxStr;
        
        (* Letzter Dateiname: *)
        OpenName        : ARRAY[0..12] OF CHAR;
        
        (* Falls TRUE, dann Programm beenden *)
        quitProg        : BOOLEAN;
        termCode        : INTEGER;      (* Return-Code f�r Shell *)
        
        (* Such- und Ersetzeinstellungen  *)
        replaceOpts,
        searchOpts      : RECORD
                            isSet,
                            doIt,
                            ignoreCase,
                            askBack,
                            onlyWord:         BOOLEAN;
                            theSearchWdw:     INTEGER;
                            direction:        EditTypes.searchDir;
                            count:            EditTypes.searchCount;
                            pos:              EditTypes.searchPos;
                            number:           INTEGER;
                            searchStr,
                            replaceStr:       ARRAY[0..79] OF CHAR;
                          END;
       
        mm2shell        : BOOLEAN; (* l„uft als Modul unter der MM2Shell *)
        
        shell           : ShellCall.shellType;  (* CLI type if available *)
        
        infoName        : ARRAY [0..255] OF CHAR;
        
        autoSavePos     : BOOLEAN;
        filterNumber    : INTEGER;
        
        oldSrcPaths     : Lists.List;
        
        (* F�r K�rzeldateien *)
        shortFileRead   : BOOLEAN;
        lastShort       : MaxStr;
        
(* Kleiner Stack f�r Keyboard-Events *)
CONST   maxKeys = 16;
TYPE    kbdEvent    = RECORD
                        kstate : BITSET;
                        scan   : CHAR;
                        ch     : CHAR;
                      END;
VAR keyStack    : ARRAY [0..maxKeys-1] OF kbdEvent;
    keyWrite    : INTEGER;
    keyRead     : INTEGER;

PROCEDURE PopKey (VAR kstate: BITSET; VAR scan : CHAR; VAR ch : CHAR);
BEGIN
  IF keyRead # keyWrite THEN
    kstate := keyStack[keyRead].kstate;
    scan   := keyStack[keyRead].scan;
    ch     := keyStack[keyRead].ch;
    keyRead := (keyRead + 1) MOD maxKeys;
  END;
END PopKey;

PROCEDURE PushKey (kstate: BITSET; scan, ch : CHAR);
BEGIN
  keyStack[keyWrite].kstate := kstate;
  keyStack[keyWrite].scan   := scan;
  keyStack[keyWrite].ch     := ch;
  keyWrite := (keyWrite + 1) MOD maxKeys;
  IF keyWrite = keyRead THEN 
    (* hat keyRead eingeholt, einmal rum! 
     * keyRead auf n„chsten setzen 
     *)
    keyRead := (keyWrite + 1) MOD maxKeys;
  END;
END PushKey;

PROCEDURE PendingKey (): BOOLEAN;
BEGIN
  RETURN keyRead # keyWrite;
END PendingKey;

PROCEDURE noWinDialAlert(); 
 (* Damit nich dauernd die Strings �berall eingesetzt werden, hier ein zentraler Aufruf *)
BEGIN 
  v.int := mtAlerts.Alert (1, NoWinDial) 
END noWinDialAlert;

CONST   cCfgName = 'fred.cfg';

PROCEDURE PathsToConf();
  VAR entry: CatTypes.Str255Ptr;
      count: INTEGER;
      varname : CatTypes.String127;
BEGIN
  Lists.ResetList (ShellMsg.SrcPaths);
  entry := Lists.NextEntry (ShellMsg.SrcPaths);
  count := 1;
  WHILE entry # NIL DO
    Strings.Assign (cSourcePath, varname, v.bool);
    Strings.Append (StrConv.IntToStr (count, 0), varname, v.bool);
    v.bool := ConfVars.SetConfigString (varname, entry^);
    entry := Lists.NextEntry (ShellMsg.SrcPaths);
    INC (count);
  END;
END PathsToConf;

(*$Z-*)
PROCEDURE findName (e, i : ADDRESS): BOOLEAN;
  VAR entry : CatTypes.Str255Ptr;
      str   : CatTypes.Str255Ptr;
BEGIN
  entry := e;
  str := i;
  RETURN AssFuncs.StrIequal (entry^, str^);
END findName;
(*$Z=*)

PROCEDURE ConfToPaths();
  VAR entry: CatTypes.Str255Ptr;
      new  : CatTypes.Str255Ptr;
      path : CatTypes.String255;
      count: INTEGER;
      varname : CatTypes.String127;
      newList : Lists.List;
      ok   : BOOLEAN;
BEGIN
  IF MOSCtrl.ModLevel = 1
  THEN
    (* Wenn unter der Shell, dann existiert die Liste schon! *)
    Lists.CreateList (ShellMsg.SrcPaths, v.bool);
  ELSE
    (* Da die d„mlicherweise in einem komischen Array gespeichert sind,
     * baue ich die Liste neu auf und setze sie am Programmende zur�ck
     *)
    Lists.CreateList (newList, v.bool);
    IF ~v.bool
    THEN
      Lists.ResetList (ShellMsg.SrcPaths);
      entry := Lists.NextEntry (ShellMsg.SrcPaths);
      WHILE entry # NIL DO
        ALLOCATE (new, LENGTH (entry^)+1);
        IF new # NIL
        THEN
          Strings.Assign (entry^, new^, v.bool);
          Lists.AppendEntry (newList, new, v.bool);
        END;
        entry := Lists.NextEntry (ShellMsg.SrcPaths);
      END;
      (* Jetzt die Listen austauschen *)
      oldSrcPaths := ShellMsg.SrcPaths;
      ShellMsg.SrcPaths := newList;
    END;
  END;
  count := 1;
  WHILE count < 255 DO
    Strings.Assign (cSourcePath, varname, v.bool);
    Strings.Append (StrConv.IntToStr (count, 0), varname, v.bool);
    IF ConfVars.GetConfigString (varname, path)
    THEN
      (* Erstmal sehen, ob der Pfad nicht schon in der Liste ist *)
      Lists.ResetList (ShellMsg.SrcPaths);
      Lists.ScanEntries (ShellMsg.SrcPaths, Lists.forward, findName, ADR(path), ok);
      IF ~ok
      THEN
        NEW (entry);
        IF entry = NIL
        THEN RETURN 
        END;
        Strings.Assign (path, entry^, v.bool);
        Lists.AppendEntry (ShellMsg.SrcPaths, entry, v.bool);
        IF v.bool THEN RETURN END;
      END;
      ConfVars.DeleteConfigVar (varname);
    END;
    INC (count);
  END;
END ConfToPaths;

PROCEDURE LoadPrefs ();
(* l„dt Default-Einstellungen und setzt diese,
 * falls kein Infofile vorhanden 
 *)
  VAR cfgFile : CatTypes.String255;
BEGIN
  (* Jetzt Infofile holen
   * Name: FRED.CFG 
   *)
  MagicStrings.Assign (homePath, infoName);
  Strings.Append (cCfgName, infoName, v.bool);
  v.bool := ConfVars.ReadConfigFile (infoName);
  ConfToPaths();
  CatGlobal.SetColors();
  IF ConfVars.GetConfigString (cPrtCfg, cfgFile)
  THEN
    Printer.LoadCFGFile (cfgFile);
  END;
END LoadPrefs;

PROCEDURE fredInfo (REF inf: mtTextfiles.TEXTFILE);
  VAR z1 : CARDINAL;
      d, m, y : CARDINAL;
      mname  : ARRAY [0..3] OF CHAR;
      tstr   : ARRAY [0..12] OF CHAR;
BEGIN
  mtTextfiles.WriteLine (inf, '# ');
  mtTextfiles.WriteLine (inf, whatString);
  mtTextfiles.WriteLn (inf);
  z1 := MagicDOS.Tgetdate();
  mtTime.DecodeDate (z1, d, m, y);
  mtTime.NameOfMonth (mtTime.English, m, mname);
  mname[3] := ' ';
  mtTextfiles.WriteLine (inf, '# created ');
  mtTextfiles.WriteLine (inf, mname);
  mtTextfiles.WriteCard (inf, d, 0);
  mtTextfiles.WriteLine (inf, ' ');
  mtTextfiles.WriteCard (inf, y, 0);
  mtTextfiles.WriteLine (inf, ', ');
  mtTime.TimeString (MagicDOS.Tgettime(), tstr);
  mtTextfiles.WriteLine (inf, tstr);
  mtTextfiles.WriteLn (inf);
END fredInfo;

PROCEDURE SavePrefs ();
BEGIN
  CatGlobal.ApplPath (infoName);
  Strings.Append (cCfgName, infoName, v.bool);
  CatEdit.EditSavePos();
  (* Pfade in Variable sichern *)
  PathsToConf();
  v.bool := ConfVars.WriteConfigFile (infoName, fredInfo);
END SavePrefs;

PROCEDURE GetHomePath();
VAR applpath:   MaxStr;
    shelPath:   MaxStr;
    shelCmd:    MaxStr;
BEGIN
  CatGlobal.SetAppl ('FRED');
  CatGlobal.GetApplPath (applpath);
  Strings.Assign (applpath, homePath, v.bool);
  (* Aktuellen Pfad holen *)
  Strings.Assign('', InPath, v.bool);
  mtDir.GetPath (InPath);
  Strings.Assign(InPath, SavePath, v.bool);
END GetHomePath;

PROCEDURE InitResource (VAR resourceName : ARRAY OF CHAR) : BOOLEAN;
  
  CONST
        noRscAlt        = '[5][Kann das Resource-File|FRED.RSC nicht laden][[Schade..]';
        
        noLowResAlt     = '[4][Die gew„hlte Aufl”sung|ist zu niedrig|f�r FRED!][ [OK ]';
        
  VAR success     : BOOLEAN;
      screenColumns : CARDINAL;
      box         : MagicAES.BoxInfo;
      rscLoaded   : BOOLEAN;
      rscString   : MaxStr;
BEGIN
  
  devHdl := mtAppl.VDIHandle;

  apId  := mtAppl.ApplIdent;
  
  GetHomePath();
  
  (* 80-Zeichen Bildschirm wird verlangt! *)
  screenColumns := mtAppl.MaxWidth DIV mtAppl.CharWidth;
  
  IF screenColumns < 80
  THEN
    v.int := mtAlerts.Alert(1,noLowResAlt);
    RETURN FALSE
  END;

  (* Resource laden und Baumaddressen ermitteln *)
  rscLoaded := MagicAES.RsrcLoad (resourceName);
  
(* Sollte eigentlich �berfl�ssig sein, da rsrcload ein shelfind macht!  *)
  IF ~rscLoaded
  THEN
    (* Auf den Shellpfaden suchen ! *)
    Paths.SearchFile (resourceName, ShellMsg.StdPaths, Paths.fromStart, v.bool, rscString);
    IF v.bool
    THEN
      rscLoaded := MagicAES.RsrcLoad (rscString);
    END;
  END;

  IF ~rscLoaded
  THEN
    Strings.Assign ('fredrsc.rsc', resourceName, v.bool);
    rscLoaded := MagicAES.RsrcLoad (resourceName);
  END;

  IF ~rscLoaded
  THEN
    mtAlerts.SetIconColor (MagicAES.RED);
    v.int := mtAlerts.Alert (1,noRscAlt);
    RETURN FALSE
  END;
  
  LoadPrefs;
  
  infoBox       := MagicAES.RsrcGaddr (MagicAES.RTREE, Fredrsc.Fileinfo);
  aboutBox      := MagicAES.RsrcGaddr (MagicAES.RTREE, Fredrsc.Aboutbox);
  lineBox       := MagicAES.RsrcGaddr (MagicAES.RTREE, Fredrsc.Linebox );
  tabBox        := MagicAES.RsrcGaddr (MagicAES.RTREE, Fredrsc.Tabbox  );
  umbruchBox    := MagicAES.RsrcGaddr (MagicAES.RTREE, Fredrsc.Umbruch );
  gotoBox       := MagicAES.RsrcGaddr (MagicAES.RTREE, Fredrsc.Gotobox );
  systemBox     := MagicAES.RsrcGaddr (MagicAES.RTREE, Fredrsc.Systembx);
  suchBox       := MagicAES.RsrcGaddr (MagicAES.RTREE, Fredrsc.Suchbox);
  pathBox       := MagicAES.RsrcGaddr (MagicAES.RTREE, Fredrsc.Pfade);
  fredIcon      := MagicAES.RsrcGaddr (MagicAES.RTREE, Fredrsc.Fredicon);
  shortBox      := MagicAES.RsrcGaddr (MagicAES.RTREE, Fredrsc.Shortbox);
  errorBox      := MagicAES.RsrcGaddr (MagicAES.RTREE, Fredrsc.Errbox);
  menu          := MagicAES.RsrcGaddr (MagicAES.RTREE, Fredrsc.Menu);
  
  (* Versionsnummer einsetzen *)
  mtUtils.SetObjcString (aboutBox, Fredrsc.Version, pVersion);
  mtUtils.SetObjcString (aboutBox, Fredrsc.Vdate, pDate);
  
  (* Bit Images anpassen *)
(*!!  
  transObj (aboutBox, Fredrsc.Edixlogo, devHdl);
  transObj (aboutBox, Fredrsc.Logo2, devHdl);
*)
(*  Behalten f�r Slider bei Laden/Speichern
  (* Infoslider anpassen: F�llmuster auf solid setzen *)
  IF Bitplanes > 1
  THEN
    box := actBox^[Infoslid].obSpec.Box;
    EXCL(box.flags,0);
    EXCL(box.flags,2);
    EXCL(box.flags,3);
    INCL(box.flags,1);
    INCL(box.flags,4);
    INCL(box.flags,5);
    INCL(box.flags,6);
    actBox^[Infoslid].obSpec.Box := box;
  END;
*)
  mtUtils.SetObjcStringAdr(systemBox, Fredrsc.Systitle, CADR(sysStrOne));
  shell := ShellCall.IsShell();
  IF shell = ShellCall.noShell THEN 
    MagicAES.MenuIenable    (menu, Fredrsc.Callshel, 0);
  END;
  
  WdwManager.EnableIconify (TRUE);
  WdwManager.SetWindowIcon (fredIcon);
  RETURN TRUE
END InitResource;

PROCEDURE InitDial (treeIdx: INTEGER; VAR tree: ADDRESS): BOOLEAN;
BEGIN
  tree := MagicAES.RsrcGaddr (MagicAES.RTREE, treeIdx);
  IF ~mtDials.NewDial (tree)
  THEN 
    EditFuncs.OutOfMem();
    RETURN FALSE
  END;
  mtDials.DialCenter (tree, mtDials.CSCREEN, 0, 0, v.r);
  RETURN TRUE
END InitDial;

PROCEDURE FormHandle(treeIdx : INTEGER):INTEGER;
VAR exit   : INTEGER;
    form   : ADDRESS;
BEGIN
  (*
  IF ~InitDial (treeIdx, form) THEN RETURN -1 END;
  MagicAES.WindUpdate(MagicAES.BEGUPDATE);
  mtDials.DialForm(form, mtDials.DSTART, v.r, v.r);
  mtDials.DialDraw(form, 0, 200, v.r, FALSE);
  exit := mtDials.DialDo(form, 0);
  exit := INTEGER(BITSET(exit) - {15});
  mtDials.DialForm(form, mtDials.DFINISH, v.r, v.r);
  MagicAES.WindUpdate(MagicAES.ENDUPDATE);
  mtUtils.ExclState(form, exit, MagicAES.SELECTED);
  mtDials.DisposeDial (form);
  *)
  form := MagicAES.RsrcGaddr (MagicAES.RTREE, treeIdx);
  exit := WinDials.WinDialDo (form, 0);
  exit := INTEGER(BITSET(exit) - {15});
  RETURN exit
END FormHandle;

PROCEDURE GetItem(dial : ADDRESS; item : INTEGER):BOOLEAN;
BEGIN
  RETURN mtUtils.InState(dial, item, MagicAES.SELECTED);
END GetItem;

PROCEDURE SetItem(dial : ADDRESS; item : INTEGER; b : BOOLEAN);
BEGIN
  mtUtils.SetState (dial, item, MagicAES.SELECTED, b);
END SetItem;

(*
PROCEDURE DoSearchDialogue(win : INTEGER);
  VAR 
      numStr:           ARRAY [0..7] OF CHAR;
      exit:             INTEGER;
      text:             EditTypes.textPtr;
      len:              LONGCARD;
      allChar,
      oneChar:          CHAR;
BEGIN
  IF CatEdit.IsEditTop (win)
  THEN
    WITH searchOpts DO 
      IF CatEdit.BlockIsMarked (win)
      THEN
        IF CatEdit.GetBlock (win, FALSE, text, len) & (text # NIL)
        THEN
          Strings.Copy (text^, 0, 39, searchStr, v.bool);
          DEALLOCATE (text, 0);
        END;
      END;
      CatEdit.GetWildChars (oneChar, allChar);
      mtUtils.SetObjcString (suchBox, Fredrsc.Sqall, allChar);
      mtUtils.SetObjcString (suchBox, Fredrsc.Sqone, oneChar);
      mtUtils.SetObjcString (suchBox, Fredrsc.Fsuchstr, searchStr);
      exit := FormHandle (Fredrsc.Suchbox);
      IF exit = Fredrsc.Fok
      THEN
        isSet := TRUE;
        (* Strings auslesen *)
        ignoreCase := GetItem (suchBox, Fredrsc.Fcase);
        onlyWord   := GetItem (suchBox, Fredrsc.Fword);
        (* Startposition suchen *)
        IF GetItem (suchBox, Fredrsc.Ffromtop) 
        THEN pos := EditTypes.fromStart; 
        ELSIF GetItem (suchBox, Fredrsc.Ffromcur) 
        THEN pos := EditTypes.fromPos; 
        END;
        direction := EditTypes.forward;
        count := EditTypes.searchOne;
        mtUtils.ObjcString (suchBox, Fredrsc.Fsuchstr, searchStr);
        mtUtils.ObjcString (suchBox, Fredrsc.Sqall, allChar);
        mtUtils.ObjcString (suchBox, Fredrsc.Sqone, oneChar);
        IF (allChar = oneChar) OR (allChar = 0c) OR (oneChar = 0c)
        THEN
          v.int := mtAlerts.Alert (1, wrongWildAlert);
        ELSE
          CatEdit.SetWildChars (oneChar, allChar);
        END;
        v.bool := CatEdit.Search (win, searchStr, pos, direction, count, number, 
                                    ignoreCase, onlyWord, FALSE);
      END;
    END;
  END;
END DoSearchDialogue;
*)

PROCEDURE searchButton (tree: ADDRESS; private: ADDRESS; button: INTEGER;
                        mx, my : INTEGER; kstate: BITSET; clicks: INTEGER): BOOLEAN;
VAR   allChar,
      oneChar:          CHAR;
BEGIN
  button := INTEGER(BITSET(button) - {15});
  mtUtils.ExclState(tree, button, MagicAES.SELECTED);
  IF button = Fredrsc.Fok
  THEN
    mtUtils.ObjcString (tree, Fredrsc.Sqall, allChar);
    mtUtils.ObjcString (tree, Fredrsc.Sqone, oneChar);
    IF (allChar = oneChar) OR (allChar = 0c) OR (oneChar = 0c)
    THEN
      v.int := mtAlerts.Alert (1, wrongWildAlert);
      WinDials.WinDialDraw (tree, button, 8, v.r, FALSE);
      RETURN FALSE
    END;
    (* String auslesen *)
    mtUtils.ObjcString (tree, Fredrsc.Fsuchstr, searchOpts.searchStr);
    (* Jetzt Suchstring �berpr�fen, ob nur Wildcards drin sind *)
    IF MagicStrings.Length (searchOpts.searchStr) = 0
    THEN 
      (* Leerer String geht auch *)
      RETURN TRUE
    END;
    (* Jetzt der eigentliche Test *)
    WHILE ((searchOpts.searchStr [0] = allChar) OR (searchOpts.searchStr[0] = oneChar)) & 
          (MagicStrings.Length (searchOpts.searchStr) > 0) DO
      MagicStrings.Delete (searchOpts.searchStr, 0, 1);
      IF MagicStrings.Length (searchOpts.searchStr) = 0
      THEN
        v.int := mtAlerts.Alert (1, noSearchStr);
        WinDials.WinDialDraw (tree, button, 8, v.r, FALSE);
      END;
    END;
    IF MagicStrings.Length (searchOpts.searchStr) > 0 THEN RETURN TRUE; END;
  ELSE
    RETURN TRUE;
  END;
  WinDials.WinDialDraw (tree, button, 8, v.r, FALSE);
  RETURN FALSE;
END searchButton;

PROCEDURE searchGetSetValues (tree: ADDRESS; private: ADDRESS; 
                              set: BOOLEAN; exit: INTEGER);
VAR   allChar,
      oneChar:          CHAR;
BEGIN
  IF set
  THEN
    CatEdit.GetWildChars (oneChar, allChar);
    mtUtils.SetObjcString (tree, Fredrsc.Sqall, allChar);
    mtUtils.SetObjcString (tree, Fredrsc.Sqone, oneChar);
    mtUtils.SetObjcString (tree, Fredrsc.Fsuchstr, searchOpts.searchStr);
  ELSE
    exit := INTEGER(BITSET(exit) - {15});
    mtUtils.ExclState(tree, exit, MagicAES.SELECTED);
    IF exit = Fredrsc.Fok
    THEN
      WITH searchOpts DO
        isSet := TRUE;
        (* Strings auslesen *)
        ignoreCase := GetItem (tree, Fredrsc.Fcase);
        onlyWord   := GetItem (tree, Fredrsc.Fword);
        (* Startposition suchen *)
        IF GetItem (tree, Fredrsc.Ffromtop)
        THEN pos := EditTypes.fromStart;
        ELSIF GetItem (tree, Fredrsc.Ffromcur)
        THEN pos := EditTypes.fromPos;
        END;
        (* Anzahl feststellen *)
        count := EditTypes.searchOne;
        (* letzte Parameter *)
        mtUtils.ObjcString (tree, Fredrsc.Sqall, allChar);
        mtUtils.ObjcString (tree, Fredrsc.Sqone, oneChar);
        IF (allChar = oneChar) OR (allChar = 0c) OR (oneChar = 0c)
        THEN
          v.int := mtAlerts.Alert (1, wrongWildAlert);
        ELSE
          CatEdit.SetWildChars (oneChar, allChar);
        END;
        mtUtils.ObjcString (tree, Fredrsc.Fsuchstr, searchStr);
        IF CatEdit.IsEditTop (theSearchWdw)
        THEN
          doIt := TRUE;
          (*
          v.bool := CatEdit.Search (theSearchWdw, searchStr, pos, direction, count, 1,
                                    ignoreCase, onlyWord, FALSE);
          *)
        END;
      END;
    END;
  END;
END searchGetSetValues;

PROCEDURE DoSearchDialogue (win: INTEGER);
VAR   form:        mtUtils.tObjcTree;
BEGIN
  form := MagicAES.RsrcGaddr (MagicAES.RTREE, Fredrsc.Suchbox);
  IF CatEdit.IsEditTop (win)
  THEN
    searchOpts.theSearchWdw := win;
    searchOpts.doIt := FALSE;
    IF ~WinDials.OpenWinDial (form, TRUE, 
                              searchGetSetValues,
                              searchGetSetValues,
                              searchButton,
                              WinDials.defDraw,
                              "",
                              NIL)
    THEN
      noWinDialAlert();
      RETURN
    END;
    WinDials.WinDialHandleEvents();
    WITH searchOpts DO
      IF doIt 
      THEN
        WdwManager.HandlePendingEvents ();
        v.bool := CatEdit.Search (theSearchWdw, searchStr, pos, direction, count, 1,
                                  ignoreCase, onlyWord, FALSE);
      END;
    END;
  END;
END DoSearchDialogue;

PROCEDURE SearchAgain (wdw : INTEGER; kstate: BITSET);
  VAR sDir: EditTypes.searchDir;
BEGIN
  IF CatEdit.IsEditTop (wdw)
  THEN
    WITH searchOpts DO 
      pos := EditTypes.fromPos;
      IF CatGlobal.WithShift (kstate)
      THEN
        IF direction = EditTypes.forward 
        THEN 
          sDir := EditTypes.backward 
        ELSE
          sDir := EditTypes.forward 
        END;
      ELSE
        sDir := direction;
      END;
      v.bool := CatEdit.Search (wdw, searchStr, pos, sDir, count, number, 
                                ignoreCase, onlyWord, TRUE);
    END;
  END;
END SearchAgain;

PROCEDURE SearchBlock (wdw: INTEGER; kstate: BITSET);
  VAR 
      text:             EditTypes.textPtr;
      len:              LONGCARD;
BEGIN
  IF CatEdit.IsEditTop (wdw)
  THEN
    WITH searchOpts DO 
      IF ~CatEdit.BlockIsMarked (wdw)
      THEN
        CatEdit.MarkWord (wdw);
      END;
      IF CatEdit.BlockIsMarked (wdw)
      THEN
        IF CatEdit.GetBlock (wdw, FALSE, FALSE, text, len) & (text # NIL)
        THEN
          Strings.Copy (text^, 0, 39, searchStr, v.bool);
          DEALLOCATE (text, 0);
        END;
      ELSE
        RETURN
      END;
      isSet := TRUE;
      IF CatGlobal.WithShift (kstate)
      THEN
        pos := EditTypes.fromStart;
      ELSE
        pos := EditTypes.fromPos;
      END;
      direction := EditTypes.forward;
      count := EditTypes.searchOne;
      onlyWord := FALSE;
      v.bool := CatEdit.Search (wdw, searchStr, pos, direction, count, number, 
                                    ignoreCase, onlyWord, FALSE);
    END;
  END;
END SearchBlock;

PROCEDURE replaceButton (tree: ADDRESS; private: ADDRESS; button: INTEGER;
                        mx, my : INTEGER; kstate: BITSET; clicks: INTEGER): BOOLEAN;
VAR   allChar,
      oneChar:          CHAR;
BEGIN
  button := INTEGER(BITSET(button) - {15});
  CASE button OF
    Fredrsc.Sgesamt,
    Fredrsc.Seinmal  : mtUtils.SetState (tree, Fredrsc.Scount, MagicAES.DISABLED, TRUE); 
                       mtUtils.SetFlag (tree, Fredrsc.Scount, MagicAES.EDITABLE, FALSE);
                       mtDials.DialDraw (tree, Fredrsc.Scount, 0, v.r, FALSE);
                       RETURN FALSE; |
    Fredrsc.Snmal    : mtUtils.SetState (tree, Fredrsc.Scount, MagicAES.DISABLED, FALSE);
                       mtUtils.SetFlag (tree, Fredrsc.Scount, MagicAES.EDITABLE, TRUE);
                       mtDials.DialDraw (tree, Fredrsc.Scount, 0, v.r, FALSE);
                       RETURN FALSE; |
    Fredrsc.Srok, 
    Fredrsc.Srquit   : mtUtils.ExclState(tree, button, MagicAES.SELECTED);
                       IF button = Fredrsc.Srok
                       THEN
                         mtUtils.ObjcString (tree, Fredrsc.Srqall, allChar);
                         mtUtils.ObjcString (tree, Fredrsc.Srqone, oneChar);
                         IF (allChar = oneChar) OR (allChar = 0c) OR (oneChar = 0c)
                         THEN
                           v.int := mtAlerts.Alert (1, wrongWildAlert);
                           WinDials.WinDialDraw (tree, button, 8, v.r, FALSE);
                           RETURN FALSE
                         END;
                         (* String auslesen *)
                         mtUtils.ObjcString (tree, Fredrsc.Ssuchstr, replaceOpts.searchStr);
                         (* Jetzt Suchstring �berpr�fen, ob nur Wildcards drin sind *)
                         IF MagicStrings.Length (replaceOpts.searchStr) = 0
                         THEN 
                           (* Leerer String geht auch *)
                           RETURN TRUE
                         END;
                         (* Jetzt der eigentliche Test *)
                         WHILE ((replaceOpts.searchStr [0] = allChar) OR (replaceOpts.searchStr[0] = oneChar)) & 
                               (MagicStrings.Length (replaceOpts.searchStr) > 0) DO
                           MagicStrings.Delete (replaceOpts.searchStr, 0, 1);
                           IF MagicStrings.Length (replaceOpts.searchStr) = 0
                           THEN
                             v.int := mtAlerts.Alert (1, noSearchStr);
                             WinDials.WinDialDraw (tree, button, 8, v.r, FALSE);
                           END;
                         END;
                         IF MagicStrings.Length (replaceOpts.searchStr) > 0 THEN RETURN TRUE; END;
                       ELSE
                         RETURN TRUE;
                       END;
                       WinDials.WinDialDraw (tree, button, 8, v.r, FALSE);
  ELSE
  END;  
  RETURN FALSE;
END replaceButton;

PROCEDURE replaceGetSetValues (tree: ADDRESS; private: ADDRESS; 
                              set: BOOLEAN; exit: INTEGER);
VAR   allChar,
      oneChar:          CHAR;
      numStr:           ARRAY [0..7] OF CHAR;
      text:             EditTypes.textPtr;
      len:              LONGCARD;
BEGIN
  IF set
  THEN
    WITH replaceOpts DO 
      IF CatEdit.BlockIsMarked (theSearchWdw)
      THEN
        IF CatEdit.GetBlock (theSearchWdw, FALSE, FALSE, text, len) & (text # NIL)
        THEN
          Strings.Copy (text^, 0, 39, searchStr, v.bool);
          DEALLOCATE (text, 0);
        END;
      END;
      CatEdit.GetWildChars (oneChar, allChar);
      mtUtils.SetObjcString (tree, Fredrsc.Srqall, allChar);
      mtUtils.SetObjcString (tree, Fredrsc.Srqone, oneChar);
      mtUtils.SetObjcString (tree, Fredrsc.Ssuchstr, searchStr);
      mtUtils.SetObjcString (tree, Fredrsc.Sreplstr, replaceStr);
      IF GetItem (tree, Fredrsc.Snmal)
      THEN
        mtUtils.SetState (tree, Fredrsc.Scount, MagicAES.DISABLED, FALSE);
        mtUtils.SetFlag (tree, Fredrsc.Scount, MagicAES.EDITABLE, TRUE);
      ELSE
        mtUtils.SetState (tree, Fredrsc.Scount, MagicAES.DISABLED, TRUE);
        mtUtils.SetFlag (tree, Fredrsc.Scount, MagicAES.EDITABLE, FALSE);
      END;
    END;
  ELSE
    exit := INTEGER(BITSET(exit) - {15});
    mtUtils.ExclState(tree, exit, MagicAES.SELECTED);
    IF exit = Fredrsc.Srok
    THEN
      WITH replaceOpts DO
        isSet := TRUE;
        (* Strings auslesen *)
        ignoreCase := GetItem (tree, Fredrsc.Scase);
        onlyWord   := GetItem (tree, Fredrsc.Sword);
        (* Startposition suchen *)
        IF GetItem (tree, Fredrsc.Sfromtop) 
        THEN 
          pos := EditTypes.fromStart; 
        ELSIF GetItem (tree, Fredrsc.Sfromcur) 
        THEN 
          pos := EditTypes.fromPos; 
        END;

        (* Suchrichtung feststellen *)
        direction := EditTypes.forward;
        (* Anzahl feststellen *)
        IF GetItem (tree, Fredrsc.Seinmal) 
        THEN 
          count := EditTypes.searchOne;
        ELSIF GetItem (tree, Fredrsc.Sgesamt)
        THEN 
          count := EditTypes.searchAll
        ELSE
          count := EditTypes.searchNum;
          mtUtils.ObjcString (tree, Fredrsc.Scount, numStr);
          v.card := 0;
          number := StrConv.StrToInt (numStr, v.card, v.bool);
        END;
        (* letzte Parameter *)
        askBack := GetItem (tree, Fredrsc.Saskback);
        (* Jetzt noch feststellen, ob Suchen oder Ersetzen *)
        mtUtils.ObjcString (tree, Fredrsc.Ssuchstr, searchStr);
        mtUtils.ObjcString (tree, Fredrsc.Sreplstr, replaceStr);
        mtUtils.ObjcString (tree, Fredrsc.Srqall, allChar);
        mtUtils.ObjcString (tree, Fredrsc.Srqone, oneChar);
        IF (allChar = oneChar) OR (allChar = 0c) OR (oneChar = 0c)
        THEN
          v.int := mtAlerts.Alert (1, wrongWildAlert);
        ELSE
          CatEdit.SetWildChars (oneChar, allChar);
        END;
        IF CatEdit.CheckWildAssign (searchStr, replaceStr)
        THEN
          doIt := TRUE;
          (*
          v.bool := CatEdit.SearchAndReplace (replaceOpts.theSearchWdw, searchStr, replaceStr, pos, direction, 
                                    count, number, ignoreCase, onlyWord, 
                                    askBack, FALSE);
          *)
        ELSE
          v.int := mtAlerts.Alert (1, wrongWildReplace);
        END;
      END;
    END;
  END;
END replaceGetSetValues;

PROCEDURE DoReplaceDialogue (win: INTEGER);
VAR   form:        mtUtils.tObjcTree;
BEGIN
  form := MagicAES.RsrcGaddr (MagicAES.RTREE, Fredrsc.Ersetzbx);
  IF CatEdit.IsEditTop (win)
  THEN
    replaceOpts.theSearchWdw := win;
    replaceOpts.doIt := FALSE;
    IF ~WinDials.OpenWinDial (form, TRUE, 
                              replaceGetSetValues,
                              replaceGetSetValues,
                              replaceButton,
                              WinDials.defDraw,
                              "",
                              NIL)
    THEN
      noWinDialAlert();
      RETURN
    END;
    WinDials.WinDialHandleEvents();
    WITH replaceOpts DO
      IF doIt 
      THEN
        WdwManager.HandlePendingEvents ();
        v.bool := CatEdit.SearchAndReplace (theSearchWdw, searchStr, replaceStr, pos, direction, 
                                            count, number, ignoreCase, onlyWord, 
                                            askBack, FALSE);
      END;
    END;
  END;
END DoReplaceDialogue;

(*
PROCEDURE DoReplaceDialogue(win : INTEGER);
  VAR 
      numStr:           ARRAY [0..7] OF CHAR;
      exit:             INTEGER;
      text:             EditTypes.textPtr;
      len:              LONGCARD;
      ersetzBox:        ADDRESS;
      allChar,
      oneChar:          CHAR;
BEGIN
  IF CatEdit.IsEditTop (win)
  THEN
    IF ~InitDial (Fredrsc.Ersetzbx, ersetzBox) THEN
      RETURN 
    END;
    WITH replaceOpts DO 
      IF CatEdit.BlockIsMarked (win)
      THEN
        IF CatEdit.GetBlock (win, FALSE, text, len) & (text # NIL)
        THEN
          Strings.Copy (text^, 0, 39, searchStr, v.bool);
          DEALLOCATE (text, 0);
        END;
      END;
      CatEdit.GetWildChars (oneChar, allChar);
      mtUtils.SetObjcString (ersetzBox, Fredrsc.Srqall, allChar);
      mtUtils.SetObjcString (ersetzBox, Fredrsc.Srqone, oneChar);
      mtUtils.SetObjcString (ersetzBox, Fredrsc.Ssuchstr, searchStr);
      mtUtils.SetObjcString (ersetzBox, Fredrsc.Sreplstr, replaceStr);
      IF GetItem (ersetzBox, Fredrsc.Snmal)
      THEN
        mtUtils.SetState (ersetzBox, Fredrsc.Scount, MagicAES.DISABLED, FALSE);
        mtUtils.SetFlag (ersetzBox, Fredrsc.Scount, MagicAES.EDITABLE, TRUE);
      ELSE
        mtUtils.SetState (ersetzBox, Fredrsc.Scount, MagicAES.DISABLED, TRUE);
        mtUtils.SetFlag (ersetzBox, Fredrsc.Scount, MagicAES.EDITABLE, FALSE);
      END;
      MagicAES.WindUpdate(MagicAES.BEGUPDATE);
      mtDials.DialForm(ersetzBox, mtDials.DSTART, v.r, v.r);
      mtDials.DialDraw(ersetzBox, 0,200, v.r, FALSE);
      LOOP
        exit := mtDials.DialDo(ersetzBox, 0);
        exit := INTEGER(BITSET(exit) - {15});
        CASE exit OF
          Fredrsc.Sgesamt,
          Fredrsc.Seinmal   : mtUtils.SetState (ersetzBox, Fredrsc.Scount, MagicAES.DISABLED, TRUE); 
                              mtUtils.SetFlag (ersetzBox, Fredrsc.Scount, MagicAES.EDITABLE, FALSE);
                              mtDials.DialDraw (ersetzBox, Fredrsc.Scount, 0, v.r, FALSE);|
          Fredrsc.Snmal     : mtUtils.SetState (ersetzBox, Fredrsc.Scount, MagicAES.DISABLED, FALSE);
                              mtUtils.SetFlag (ersetzBox, Fredrsc.Scount, MagicAES.EDITABLE, TRUE);
                              mtDials.DialDraw (ersetzBox, Fredrsc.Scount, 0, v.r, FALSE);|
          Fredrsc.Srok,
          Fredrsc.Srquit   : EXIT |
        ELSE
        END;  
      END;
      mtDials.DialForm(ersetzBox, mtDials.DFINISH, v.r, v.r);
      MagicAES.WindUpdate(MagicAES.ENDUPDATE);
      mtUtils.ExclState(ersetzBox, exit, MagicAES.SELECTED);
      IF exit = Fredrsc.Srok
      THEN
        isSet := TRUE;
        (* Strings auslesen *)
        ignoreCase := GetItem (ersetzBox, Fredrsc.Scase);
        onlyWord   := GetItem (ersetzBox, Fredrsc.Sword);
        (* Startposition suchen *)
        IF GetItem (ersetzBox, Fredrsc.Sfromtop) 
        THEN pos := EditTypes.fromStart; 
        ELSIF GetItem (ersetzBox, Fredrsc.Sfromcur) 
        THEN pos := EditTypes.fromPos; 
        END;
        (* Suchrichtung feststellen *)
        direction := EditTypes.forward;
        (* Anzahl feststellen *)
        IF GetItem (ersetzBox, Fredrsc.Seinmal) 
        THEN count := EditTypes.searchOne;
        ELSIF GetItem (ersetzBox, Fredrsc.Sgesamt)
        THEN count := EditTypes.searchAll
        ELSE
          count := EditTypes.searchNum;
          mtUtils.ObjcString (ersetzBox, Fredrsc.Scount, numStr);
          v.card := 0;
          number := StrConv.StrToInt (numStr, v.card, v.bool);
        END;
        (* letzte Parameter *)
        askBack := GetItem (ersetzBox, Fredrsc.Saskback);
        (* Jetzt noch feststellen, ob Suchen oder Ersetzen *)
        mtUtils.ObjcString (ersetzBox, Fredrsc.Ssuchstr, searchStr);
        mtUtils.ObjcString (ersetzBox, Fredrsc.Sreplstr, replaceStr);
        mtUtils.ObjcString (ersetzBox, Fredrsc.Srqall, allChar);
        mtUtils.ObjcString (ersetzBox, Fredrsc.Srqone, oneChar);
        IF (allChar = oneChar) OR (allChar = 0c) OR (oneChar = 0c)
        THEN
          v.int := mtAlerts.Alert (1, wrongWildAlert);
        ELSE
          CatEdit.SetWildChars (oneChar, allChar);
        END;
        IF CatEdit.CheckWildAssign (searchStr, replaceStr)
        THEN
          v.bool := CatEdit.SearchAndReplace (win, searchStr, replaceStr, pos, direction, 
                                    count, number, ignoreCase, onlyWord, 
                                    askBack, FALSE);
        ELSE
          v.int := mtAlerts.Alert (1, wrongWildReplace);
        END;
      END;
    END;
    mtDials.DisposeDial (ersetzBox);
  END;
END DoReplaceDialogue;
*)

PROCEDURE ReplaceAgain (wdw : INTEGER; kstate : BITSET);
  VAR sDir: EditTypes.searchDir;
BEGIN
  IF CatEdit.IsEditTop (wdw)
  THEN
    WITH replaceOpts DO 
      pos := EditTypes.fromPos;
      IF CatGlobal.WithShift (kstate)
      THEN
        IF direction = EditTypes.forward 
        THEN 
          sDir := EditTypes.backward 
        ELSE
          sDir := EditTypes.forward 
        END;
      ELSE
        sDir := direction;
      END;
      v.bool := CatEdit.SearchAndReplace (wdw, searchStr, replaceStr, pos, sDir, 
                                count, number, ignoreCase, onlyWord, 
                                askBack, TRUE);
    END;
  END;
END ReplaceAgain;

  TYPE Trick =  POINTER TO RECORD
                  CASE : BOOLEAN OF
                    TRUE:  wert: INTEGER;|
                    FALSE: hi: CHAR;
                           lo: CHAR;|
                  END;
                 END;

PROCEDURE SetXString (tree  : ADDRESS; obj: INTEGER;
                      sTree : ADDRESS; idx: INTEGER);
  VAR t       : Trick;
      selStr  : ARRAY [0..40] OF CHAR;
BEGIN
  mtUtils.ObjcString (sTree, idx+1, selStr);
  mtUtils.SetObjcString (tree, obj, selStr);
END SetXString;

PROCEDURE SetXState (tree : ADDRESS; obj: INTEGER; xState : INTEGER);
  VAR t : Trick;
      tr: mtUtils.tObjcTree;
BEGIN
  tr := tree;
  t := ADR (tr^[obj].obState);
  t^.hi := CHR(xState);
END SetXState;

PROCEDURE GetXState (tree : ADDRESS; obj: INTEGER) : INTEGER;
  VAR t : Trick;
      tr: mtUtils.tObjcTree;
BEGIN
  tr := tree;
  t := ADR (tr^[obj].obState);
  RETURN INTEGER(ORD (t^.hi));
END GetXState;

PROCEDURE SetIntStr (tree: ADDRESS; obj: INTEGER; val : INTEGER);
  VAR str : ARRAY [0..79] OF CHAR;
BEGIN
  MagicConvert.IntToStr (val, 0, str);
  mtUtils.SetObjcString (tree, obj, str);
END SetIntStr;

PROCEDURE GetIntStr (tree: ADDRESS; obj: INTEGER; VAR val : INTEGER);
  VAR str : ARRAY [0..79] OF CHAR;
      lval: LONGINT;
BEGIN
  mtUtils.ObjcString (tree, obj, str);
  lval := MagicConvert.StrToLInt (str);
  IF (lval > MAX(INTEGER)) THEN val := MAX(INTEGER)
  ELSIF (lval < MIN(INTEGER)) THEN val := MIN (INTEGER)
  ELSE
    val := SHORT (lval)
  END;
END GetIntStr;

(*
PROCEDURE doFilter (VAR filterNumber: INTEGER; VAR cmd: ARRAY OF CHAR): BOOLEAN;
  VAR but       : INTEGER;
      filtSel   : mtUtils.tObjcTree;
      filterBox : mtUtils.tObjcTree;
      t         : Trick;
      i,
      x, y, 
      select    : INTEGER;
      varname   : CatTypes.String127;
BEGIN
  filtSel := MagicAES.RsrcGaddr (MagicAES.RTREE, Fredrsc.Filtsel);
  IF ~InitDial (Fredrsc.Filtbox, filterBox)
  THEN
    RETURN FALSE
  END;
  mtUtils.SetObjcString (filterBox, Fredrsc.Fbcomm, "");
  FOR i := 7 TO 10 DO
    MagicStrings.Assign (cFilter, varname);
    MagicStrings.Append (StrConv.IntToStr (i-6, 0), varname);
    IF ConfVars.GetConfigString (varname, cmd)
    THEN
      IF i - 1 = filterNumber
      THEN
        (* String setzen *)
        mtUtils.SetObjcString (filterBox, Fredrsc.Fbcomm, cmd);
      END;
      MagicStrings.Insert (' ', cmd, 0);
    ELSE
      (* Extern X anlegen *)
      MagicStrings.Assign (' Extern ', cmd);
      MagicStrings.Append (StrConv.IntToStr (i-6, 0), cmd);
    END;
    mtUtils.SetObjcString (filtSel, i, cmd);
  END;
  IF shell = ShellCall.noShell
  THEN
    FOR i := 7 TO 10 DO
      mtUtils.InclState (filtSel, i, MagicAES.DISABLED);
      mtUtils.ExclFlag (filtSel, i, MagicAES.SELECTABLE);
    END;
  END;
  (* vorbereiten *)
  SetXState (filterBox, Fredrsc.Fbfilt1, filterNumber);
  SetXString (filterBox, Fredrsc.Fbfilt1, filtSel, filterNumber);
  mtDials.DialForm (filterBox, mtDials.DSTART, v.r, v.r);
  mtDials.DialDraw (filterBox, 0, 99, v.r, FALSE);
  LOOP
    but := mtDials.DialDo (filterBox, 0);
    but := INTEGER(BITSET(but) - {15});
    CASE but OF
      Fredrsc.Fbok,
      Fredrsc.Fbquit : EXIT |
      (*
      Fredrsc.Fbhelp : 
        mtDials.DialForm (filterBox, mtDials.DDISABLE, v.r, v.r);
        CatHelp.DoHelp (CatHelp.filter);
        mtDials.DialForm (filterBox, mtDials.DENABLE, v.r, v.r); 
        mtUtils.ExclState (filterBox, but, MagicAES.SELECTED);
        mtDials.DialDraw (filterBox, but, 1, v.r, FALSE); |
      *)
      Fredrsc.Fbfilt0,
      Fredrsc.Fbfilt1:
        IF but = Fredrsc.Fbfilt0 THEN but:= Fredrsc.Fbfilt1 END;
        MagicAES.ObjcOffset (filterBox, but, x, y);
        t := ADR (filterBox^[but].obState);
        select := mtPopups.TreePopup (filtSel, x, y, ORD(t^.hi))-1;
        IF (shell = ShellCall.noShell) & (select > 5) THEN select := -1 END;
        IF select >= 0 THEN
          t^.hi := CHR(select);
          SetXString (filterBox, but, filtSel, select);
          IF select > 5
          THEN
            MagicStrings.Assign (cFilter, varname);
            MagicStrings.Append (StrConv.IntToStr (select-5, 0), varname);
            ConfVars.GetConfDefStr (varname, cmd, "");
            mtUtils.SetObjcString (filterBox, Fredrsc.Fbcomm, cmd);
          ELSE
            mtUtils.SetObjcString (filterBox, Fredrsc.Fbcomm, '');
          END;
          mtDials.DialDraw (filterBox, Fredrsc.Fbcomm, 0, v.r, FALSE);
          mtDials.DialDraw (filterBox, but, 0, v.r, FALSE);
        END; |
      Fredrsc.Fbfilt2:
        t := ADR (filterBox^[but-1].obState);
        IF shell # ShellCall.noShell
        THEN
          t^.hi := CHR((ORD(t^.hi)+1) MOD 10);
        ELSE
          t^.hi := CHR((ORD(t^.hi)+1) MOD 6);
        END;
        select := ORD (t^.hi);
        SetXString (filterBox, but-1, filtSel, select);
        IF select > 5
        THEN
          MagicStrings.Assign (cFilter, varname);
          MagicStrings.Append (StrConv.IntToStr (select-5, 0), varname);
          ConfVars.GetConfDefStr (varname, cmd, "");
          mtUtils.SetObjcString (filterBox, Fredrsc.Fbcomm, cmd);
        ELSE
          mtUtils.SetObjcString (filterBox, Fredrsc.Fbcomm, '');
        END;
        mtDials.DialDraw (filterBox, Fredrsc.Fbcomm, 0, v.r, FALSE);
        mtDials.DialDraw (filterBox, but-1, 0, v.r, FALSE); |
    END;
  END; (* LOOP *)
  IF but = Fredrsc.Fbok
  THEN
    filterNumber := GetXState (filterBox, Fredrsc.Fbfilt1);
    IF filterNumber > 5
    THEN
      (* String auslesen *)
      mtUtils.ObjcString (filterBox, Fredrsc.Fbcomm, cmd);
      MagicStrings.Assign (cFilter, varname);
      MagicStrings.Append (StrConv.IntToStr (filterNumber-5, 0), varname);
      v.bool := ConfVars.SetConfigString (varname, cmd);
    END;
  END; 
  mtUtils.ExclState (filterBox, but, MagicAES.SELECTED);
  mtDials.DialForm (filterBox, mtDials.DFINISH, v.r, v.r);
  mtDials.DisposeDial (filterBox);
  RETURN but = Fredrsc.Fbok;
END doFilter;
*)

PROCEDURE buildVarName (REF name: ARRAY OF CHAR; number: INTEGER; VAR newName: ARRAY OF CHAR);
BEGIN
  Strings.Assign (name, newName, v.bool);
  Strings.Append (StrConv.IntToStr (number, 0), newName, v.bool);
END buildVarName;

  CONST lowExtern = 8;
        highExtern = 15;
        filtMax    = 15;
        filtExt    = 8;

PROCEDURE BuildFilterPopup (VAR filterNumber: INTEGER; VAR filtSel : mtUtils.tObjcTree; 
                            forDial: BOOLEAN);
  VAR i         : INTEGER;
      varname   : CatTypes.String127;
      cmd       : CatTypes.String127;
      filterBox : mtUtils.tObjcTree;
      isDa      : BOOLEAN;
BEGIN
  filterBox := MagicAES.RsrcGaddr (MagicAES.RTREE, Fredrsc.Filtbox);
  filtSel   := MagicAES.RsrcGaddr (MagicAES.RTREE, Fredrsc.Filtsel);
  mtUtils.SetObjcString (filterBox, Fredrsc.Fbcomm, "");
  FOR i := lowExtern TO highExtern DO
    buildVarName (cFilter, i-lowExtern+1, varname);
    isDa := ConfVars.GetConfigString (varname, cmd);
    IF isDa
    THEN
      IF i - 1 = filterNumber
      THEN
        (* String setzen *)
        mtUtils.SetObjcString (filterBox, Fredrsc.Fbcomm, cmd);
      END;
      MagicStrings.Insert (' ', cmd, 0);
    ELSE
      (* Extern X anlegen *)
      MagicStrings.Assign (' Extern ', cmd);
      MagicStrings.Append (StrConv.IntToStr (i-lowExtern+1, 0), cmd);
    END;
    mtUtils.SetState (filtSel, i, MagicAES.DISABLED, ~isDa & ~forDial);
    mtUtils.SetFlag  (filtSel, i, MagicAES.SELECTABLE, isDa OR forDial);
    mtUtils.SetObjcString (filtSel, i, cmd);
  END;
  IF ShellCall.IsShell() = ShellCall.noShell
  THEN
    FOR i := lowExtern TO highExtern DO
      mtUtils.InclState (filtSel, i, MagicAES.DISABLED);
      mtUtils.ExclFlag (filtSel, i, MagicAES.SELECTABLE);
    END;
  END;
END BuildFilterPopup;

TYPE    blockInfo   = RECORD
                        filterNumber    : INTEGER;
                        cmd             : CatTypes.String255;
                        exitBut         : INTEGER;
                        filtSel : mtUtils.tObjcTree;
                      END;
        blockInfoPtr = POINTER TO blockInfo;
        
PROCEDURE blockButton (obTree: ADDRESS; private: ADDRESS; button: INTEGER;
                       mx, my : INTEGER; kstate: BITSET; clicks: INTEGER): BOOLEAN;
VAR infoPtr : blockInfoPtr;
    but     : INTEGER;
    t       : Trick;
    x, y, 
    select  : INTEGER;
    varname : CatTypes.String127;
    tree    : mtUtils.tObjcTree;
BEGIN
  infoPtr := private;
  tree := obTree;
  but := INTEGER(BITSET(button) - {15});
  CASE but OF
    Fredrsc.Fbok,
    Fredrsc.Fbquit : 
      mtUtils.ExclState (tree, but, MagicAES.SELECTED);
      RETURN TRUE; |
      (*
    Fredrsc.Fbhelp : 
      CatHelp.DoHelp (CatHelp.filter);
      mtUtils.ExclState (tree, but, MagicAES.SELECTED);
      mtDials.DialDraw (tree, but, 1, v.r, FALSE); |
      *)
    Fredrsc.Fbfilt0,
    Fredrsc.Fbfilt1:
      but := Fredrsc.Fbfilt1;
      MagicAES.ObjcOffset (tree, but, x, y);
      t := ADR (tree^[but].obState);
      select := mtPopups.TreePopup (infoPtr^.filtSel, x, y, ORD(t^.hi))-1;
      IF (ShellCall.IsShell() = ShellCall.noShell) & (select >= lowExtern) THEN select := -1 END;
      IF select >= 0 THEN
        t^.hi := CHR(select);
        SetXString (tree, but, infoPtr^.filtSel, select);
        IF select >= lowExtern-1
        THEN
          buildVarName (cFilter, select-lowExtern+2, varname);
          ConfVars.GetConfDefStr (varname, infoPtr^.cmd, "");
          mtUtils.SetObjcString (tree, Fredrsc.Fbcomm, infoPtr^.cmd);
        ELSE
          mtUtils.SetObjcString (tree, Fredrsc.Fbcomm, '');
        END;
        mtDials.DialDraw (tree, Fredrsc.Fbcomm, 0, v.r, FALSE);
        mtDials.DialDraw (tree, but, 0, v.r, FALSE);
      END; |
    Fredrsc.Fbfilt2:
      t := ADR (tree^[but-1].obState);
      IF (ShellCall.IsShell() # ShellCall.noShell)
      THEN
        t^.hi := CHR((ORD(t^.hi)+1) MOD filtMax);
      ELSE
        t^.hi := CHR((ORD(t^.hi)+1) MOD (filtMax - filtExt));
      END;
      select := ORD (t^.hi);
      SetXString (tree, but-1, infoPtr^.filtSel, select);
      IF select >= lowExtern-1
      THEN
        buildVarName (cFilter, select-lowExtern+2, varname);
        ConfVars.GetConfDefStr (varname, infoPtr^.cmd, "");
        mtUtils.SetObjcString (tree, Fredrsc.Fbcomm, infoPtr^.cmd);
      ELSE
        mtUtils.SetObjcString (tree, Fredrsc.Fbcomm, '');
      END;
      mtDials.DialDraw (tree, Fredrsc.Fbcomm, 0, v.r, FALSE);
      mtDials.DialDraw (tree, but-1, 0, v.r, FALSE); |
  ELSE
  END;
  RETURN FALSE;
END blockButton;

PROCEDURE blockGetSetValues (tree: ADDRESS; private: ADDRESS; 
                             set: BOOLEAN; exit: INTEGER);
VAR infoPtr : blockInfoPtr;
    varname : CatTypes.String127;
BEGIN
  infoPtr := private;
  infoPtr^.exitBut := INTEGER(BITSET(exit) - {15});
  IF set
  THEN
    BuildFilterPopup (infoPtr^.filterNumber, infoPtr^.filtSel, TRUE);
    (* vorbereiten *)
    SetXState (tree, Fredrsc.Fbfilt1, infoPtr^.filterNumber);
    SetXString (tree, Fredrsc.Fbfilt1, infoPtr^.filtSel, infoPtr^.filterNumber);
  ELSE
    IF infoPtr^.exitBut = Fredrsc.Fbok
    THEN
      infoPtr^.filterNumber := GetXState (tree, Fredrsc.Fbfilt1);
      IF infoPtr^.filterNumber >= lowExtern-1
      THEN
        (* String auslesen *)
        mtUtils.ObjcString (tree, Fredrsc.Fbcomm, infoPtr^.cmd);
        buildVarName (cFilter, infoPtr^.filterNumber-lowExtern+2, varname);
        v.bool := ConfVars.SetConfigString (varname, infoPtr^.cmd);
      END;
    END; 
  END;
END blockGetSetValues;

PROCEDURE doFilter (VAR filterNumber: INTEGER; VAR cmd: ARRAY OF CHAR): BOOLEAN;
  VAR filterBox : mtUtils.tObjcTree;
      infoPtr   : blockInfoPtr;
      result    : BOOLEAN;
BEGIN
  IF filterNumber < 0 THEN filterNumber := 0; END;
  filterBox := MagicAES.RsrcGaddr (MagicAES.RTREE, Fredrsc.Filtbox);
  NEW (infoPtr);
  IF infoPtr=NIL
  THEN
    RETURN FALSE;
  END;
  MagicStrings.Assign (cmd, infoPtr^.cmd);
  infoPtr^.filterNumber := filterNumber;
  
  IF ~WinDials.OpenWinDial (filterBox, TRUE, 
                            blockGetSetValues,
                            blockGetSetValues,
                            blockButton,
                            WinDials.defDraw,
                            "",
                            infoPtr)
  THEN
    noWinDialAlert();
    DISPOSE (infoPtr);
    RETURN FALSE;
  END;
  (* Da wir die Ergebnisse brauchen, m�ssen wir hier die Eventroutine 
   * aufrufen 
   *)
  WinDials.WinDialHandleEvents();
  
  filterNumber := infoPtr^.filterNumber;
  MagicStrings.Assign (infoPtr^.cmd, cmd);

  result := infoPtr^.exitBut = Fredrsc.Fbok;
  
  DISPOSE (infoPtr);
  
  RETURN result;
  
END doFilter;

PROCEDURE doPopupFilter (VAR filterNumber: INTEGER; VAR cmd: ARRAY OF CHAR): BOOLEAN;
  VAR but       : INTEGER;
      filtSel   : mtUtils.tObjcTree;
      varname   : CatTypes.String127;
      x, y      : INTEGER;
      fNumber   : INTEGER;
BEGIN
  IF filterNumber < 0 THEN filterNumber := 0; END;
  BuildFilterPopup (filterNumber, filtSel, FALSE);
  MagicAES.GrafMkstate (x, y, v.bset, v.bset);
  fNumber := mtPopups.TreePopup (filtSel, x, y, 0) - 1;
  IF fNumber >= 0
  THEN
    filterNumber := fNumber;
  END;
  IF fNumber >= lowExtern-1
  THEN
    (* String auslesen *)
    buildVarName (cFilter, fNumber-lowExtern+2, varname);
    IF ConfVars.GetConfigString (varname, cmd)
    THEN
      RETURN TRUE;
    END;
    RETURN FALSE
  END;
  RETURN fNumber >= 0
END doPopupFilter;


TYPE    printerInfo = RECORD
                        cfgFile       : CatTypes.String255;
                        cfgPath       : CatTypes.pathStrType;
                        cfgName       : CatTypes.nameStrType;
                        cfgExt        : CatTypes.extStrType;
                      END;
        prInfoPtr   = POINTER TO printerInfo;

PROCEDURE printerButton (tree: ADDRESS; private: ADDRESS; button: INTEGER;
                          mx, my : INTEGER; kstate: BITSET; clicks: INTEGER): BOOLEAN;
  VAR but           : INTEGER;
      prnConf,
      prnStyleSel,
      prnIFSel      : mtUtils.tObjcTree;
      x, y          : INTEGER;
      select        : INTEGER;
      selStr        : ARRAY [0..40] OF CHAR;
      t             : Trick;
      res           : BOOLEAN;
      name          : CatTypes.String127;
      prInfo        : prInfoPtr;
BEGIN
  prInfo := private;

  prnStyleSel := MagicAES.RsrcGaddr (MagicAES.RTREE, Fredrsc.Psizebox);
  prnIFSel    := MagicAES.RsrcGaddr (MagicAES.RTREE, Fredrsc.Ifbox);

  prnConf := tree;
  but := INTEGER(BITSET(button) - {15});
  CASE but OF
    Fredrsc.Oprtsiz0,
    Fredrsc.Oprtsiz1:
           but := Fredrsc.Oprtsiz1;
           MagicAES.ObjcOffset (tree, but, x, y);
           t := ADR (prnConf^[but].obState);
           select := mtPopups.TreePopup (prnStyleSel, x, y, ORD(t^.hi))-1;
           IF select >= 0 THEN
             t^.hi := CHR(select);
             SetXString (tree, but, prnStyleSel, select);
             WinDials.WinDialDraw (tree, but, 0, v.r, FALSE);
           END;|
    Fredrsc.Oprtsiz2:
           t := ADR (prnConf^[but-1].obState);
           t^.hi := CHR((ORD(t^.hi)+1) MOD 3);
           select := ORD (t^.hi);
           SetXString (tree, but-1, prnStyleSel, select);
           WinDials.WinDialDraw (tree, but-1, 0, v.r, FALSE); |
    Fredrsc.Ointerfc0,
    Fredrsc.Ointerfc1: 
           but := Fredrsc.Ointerfc1;
           MagicAES.ObjcOffset (tree, but, x, y);
           t := ADR (prnConf^[but].obState);
           select := mtPopups.TreePopup (prnIFSel, x, y, ORD(t^.hi))-1;
           IF select >= 0 THEN
             t^.hi := CHR(select);
             SetXString (tree, but, prnIFSel, select);
             WinDials.WinDialDraw (tree, but, 0, v.r, FALSE);
           END;|
    Fredrsc.Ointerfc2:
           t := ADR (prnConf^[but-1].obState);
           t^.hi := CHR((ORD(t^.hi)+1) MOD 2);
           select := ORD (t^.hi);
           SetXString (tree, but-1, prnIFSel, select);
           WinDials.WinDialDraw (tree, but-1, 0, v.r, FALSE); |
    Fredrsc.Oselcfg0,
    Fredrsc.Oselcfg:
           but := Fredrsc.Oselcfg;
           res := CatGlobal.FselGet (prInfo^.cfgPath, prInfo^.cfgName, '*.cfg', 'CFG-Datei ausw„hlen', TRUE);
           IF res & (prInfo^.cfgName[0] # '')
           THEN
             MagicStrings.Assign (prInfo^.cfgPath, prInfo^.cfgFile);
             MagicStrings.Append (prInfo^.cfgName, prInfo^.cfgFile);
             Printer.LoadCFGFile (prInfo^.cfgFile);
             IF Printer.Response = Printer.CFGnotFound
             THEN
               v.int := mtAlerts.Alert (1, cfgNotFound);
             ELSIF Printer.Response = Printer.wrongIdent
             THEN
               v.int := mtAlerts.Alert (1, noCfgFile);
             ELSIF Printer.Response = Printer.done
             THEN
               Printer.GetPrnName (name);
               mtUtils.SetObjcString (tree, Fredrsc.Oselcfg, prInfo^.cfgName);
               mtUtils.SetObjcString (tree, Fredrsc.Printname, name);
               mtUtils.CalcArea (tree, Fredrsc.Printname, v.r);
               WinDials.WinDialDraw (tree, 0, 8, v.r, TRUE);
             END;
           ELSIF res
           THEN
             Printer.FreeCFGFile();
             MagicStrings.Assign ('', prInfo^.cfgFile);
             Printer.GetPrnName (name);
             mtUtils.SetObjcString (tree, Fredrsc.Printname, name);
             MagicStrings.Assign ('noname.cfg',prInfo^.cfgName);
             mtUtils.SetObjcString (tree, Fredrsc.Oselcfg, prInfo^.cfgName);
             mtUtils.CalcArea (tree, Fredrsc.Printname, v.r);
             WinDials.WinDialDraw (tree, 0, 8, v.r, TRUE);
           END; 
           mtUtils.ExclState (tree, but, MagicAES.SELECTED);
           WinDials.WinDialDraw (tree, but, 0, v.r, FALSE); |  
    Fredrsc.Prok,
    Fredrsc.Prcancel: 
           mtUtils.ExclState (tree, but, MagicAES.SELECTED);
           RETURN TRUE; |
  ELSE
  END;
  RETURN FALSE;
END printerButton;

PROCEDURE printerGetSetValues (tree: ADDRESS; private: ADDRESS; 
                               set: BOOLEAN; exit: INTEGER);
VAR prnStyleSel,
    prnIFSel    : mtUtils.tObjcTree;
    val         : BOOLEAN;
    intVal      : INTEGER;
    name        : ARRAY [0..79] OF CHAR;
    prInfo      : prInfoPtr;
BEGIN
  prInfo := private;

  prnStyleSel := MagicAES.RsrcGaddr (MagicAES.RTREE, Fredrsc.Psizebox);
  prnIFSel    := MagicAES.RsrcGaddr (MagicAES.RTREE, Fredrsc.Ifbox);

  IF set
  THEN (* set *)
    (* Noch Namen des CFG-Files *)
    IF ConfVars.GetConfigString (cPrtCfg, prInfo^.cfgFile)
    THEN
      mtDir.SplitPath (prInfo^.cfgFile, prInfo^.cfgPath, prInfo^.cfgName, prInfo^.cfgExt);
    ELSE
      MagicStrings.Assign ('', prInfo^.cfgFile);
      MagicStrings.Assign ('noname.cfg', prInfo^.cfgName);
      MagicStrings.Assign (homePath,prInfo^.cfgPath);
    END;
    mtUtils.SetObjcString (tree, Fredrsc.Oselcfg, prInfo^.cfgName);

    ConfVars.GetConfDefInt (cPrtMargin, intVal, 0);
    SetIntStr (tree, Fredrsc.Oprleftm, intVal);
    ConfVars.GetConfDefInt (cPrtLines, intVal, 0);
    intVal := intVal MOD 10;  (* Maximal 0 bis 9 *)
    SetIntStr (tree, Fredrsc.Oprlines, intVal);
    ConfVars.GetConfDefBool (cPrtNlq, val, FALSE);
    mtUtils.SetState (tree, Fredrsc.Oprnnlq, MagicAES.SELECTED, val);
    ConfVars.GetConfDefBool (cPrtFF, val, FALSE);
    mtUtils.SetState (tree, Fredrsc.Oformfeed, MagicAES.SELECTED, val);
    Printer.GetPrnName (name);
    mtUtils.SetObjcString (tree, Fredrsc.Printname, name);
    ConfVars.GetConfDefInt (cPrtPort, intVal, 0);
    SetXState (tree, Fredrsc.Ointerfc1, ORD(intVal));
    SetXString (tree, Fredrsc.Ointerfc1, prnIFSel, ORD(intVal));
    ConfVars.GetConfDefInt (cPrtStyle, intVal, 0);
    SetXState (tree, Fredrsc.Oprtsiz1, ORD(intVal));
    SetXString (tree, Fredrsc.Oprtsiz1, prnStyleSel, ORD(intVal));
  ELSE
    IF exit = Fredrsc.Prok
    THEN
      v.bool := ConfVars.SetConfigInt  (cPrtPort, GetXState (tree, Fredrsc.Ointerfc1));
      v.bool := ConfVars.SetConfigInt  (cPrtStyle, GetXState (tree, Fredrsc.Oprtsiz1));
      v.bool := ConfVars.SetConfigBool (cPrtNlq, mtUtils.InState (tree, Fredrsc.Oprnnlq, MagicAES.SELECTED));
      v.bool := ConfVars.SetConfigBool (cPrtFF, mtUtils.InState (tree, Fredrsc.Oformfeed, MagicAES.SELECTED));
      GetIntStr (tree, Fredrsc.Oprleftm, intVal);
      v.bool := ConfVars.SetConfigInt (cPrtMargin, intVal);
      GetIntStr (tree, Fredrsc.Oprlines, intVal);
      v.bool := ConfVars.SetConfigInt (cPrtLines, intVal);
      IF prInfo^.cfgFile[0] # '' THEN v.bool := ConfVars.SetConfigString (cPrtCfg, prInfo^.cfgFile); END;
    ELSE
      ConfVars.GetConfDefStr (cPrtCfg, prInfo^.cfgFile, '');
      IF prInfo^.cfgFile[0] # '' THEN Printer.LoadCFGFile (prInfo^.cfgFile); END;
    END;
    DISPOSE (prInfo);
  END;
END printerGetSetValues;

PROCEDURE doPrinter();
VAR printConf   : mtUtils.tObjcTree;
      prInfo    : prInfoPtr;
      
  
BEGIN
  printConf := MagicAES.RsrcGaddr (MagicAES.RTREE, Fredrsc.Prnconf);
  
  NEW (prInfo);
  IF prInfo = NIL
  THEN
    RETURN
  END;
  IF ~WinDials.OpenWinDial (printConf, FALSE, 
                            printerGetSetValues,
                            printerGetSetValues,
                            printerButton,
                            WinDials.defDraw,
                            "",
                            prInfo)
  THEN
    DISPOSE (prInfo);
    noWinDialAlert();
  END;
END doPrinter;

(*
PROCEDURE doPrinter();
VAR printConf,
    prnStyleSel,
    prnIFSel    : mtUtils.tObjcTree;


  PROCEDURE setGetOpts (setOrGet : BOOLEAN);
    VAR val : BOOLEAN;
        intVal : INTEGER;
        name   : ARRAY [0..79] OF CHAR;
  BEGIN
    IF setOrGet
    THEN (* set *)
      ConfVars.GetConfDefInt (cPrtMargin, intVal, 0);
      intVal := intVal MOD 10;  (* Maximal 0 bis 9 *)
      SetIntStr (printConf, Fredrsc.Oprleftm, intVal);
      ConfVars.GetConfDefInt (cPrtLines, intVal, 0);
      intVal := intVal MOD 10;  (* Maximal 0 bis 9 *)
      SetIntStr (printConf, Fredrsc.Oprlines, intVal);
      ConfVars.GetConfDefBool (cPrtNlq, val, FALSE);
      mtUtils.SetState (printConf, Fredrsc.Oprnnlq, MagicAES.SELECTED, val);
      ConfVars.GetConfDefBool (cPrtFF, val, FALSE);
      mtUtils.SetState (printConf, Fredrsc.Oformfeed, MagicAES.SELECTED, val);
      Printer.GetPrnName (name);
      mtUtils.SetObjcString (printConf, Fredrsc.Printname, name);
      mtUtils.SetObjcString (printConf, Fredrsc.Oselcfg, '');
      ConfVars.GetConfDefInt (cPrtPort, intVal, 0);
      SetXState (printConf, Fredrsc.Ointerfc1, ORD(intVal));
      SetXString (printConf, Fredrsc.Ointerfc1, prnIFSel, ORD(intVal));
      ConfVars.GetConfDefInt (cPrtStyle, intVal, 0);
      SetXState (printConf, Fredrsc.Oprtsiz1, ORD(intVal));
      SetXString (printConf, Fredrsc.Oprtsiz1, prnStyleSel, ORD(intVal));
    ELSE
      v.bool := ConfVars.SetConfigInt  (cPrtPort, GetXState (printConf, Fredrsc.Ointerfc1));
      v.bool := ConfVars.SetConfigInt  (cPrtStyle, GetXState (printConf, Fredrsc.Oprtsiz1));
      v.bool := ConfVars.SetConfigBool (cPrtNlq, mtUtils.InState (printConf, Fredrsc.Oprnnlq, MagicAES.SELECTED));
      v.bool := ConfVars.SetConfigBool (cPrtFF, mtUtils.InState (printConf, Fredrsc.Oformfeed, MagicAES.SELECTED));
      GetIntStr (printConf, Fredrsc.Oprleftm, intVal);
      v.bool := ConfVars.SetConfigInt (cPrtMargin, intVal);
      GetIntStr (printConf, Fredrsc.Oprlines, intVal);
      v.bool := ConfVars.SetConfigInt (cPrtLines, intVal);
    END;
  END setGetOpts;
       
  VAR but       : INTEGER;
      x, y      : INTEGER;
      select    : INTEGER;
      selStr    : ARRAY [0..40] OF CHAR;
      t         : Trick;
      cfgFile   : CatTypes.String255;
      cfgPath   : CatTypes.pathStrType;
      cfgName   : CatTypes.nameStrType;
      cfgExt    : CatTypes.extStrType;
      prnConf   : mtUtils.tObjcTree;
      res       : BOOLEAN;
      name      : CatTypes.String127;
      
  
BEGIN
  prnStyleSel := MagicAES.RsrcGaddr (MagicAES.RTREE, Fredrsc.Psizebox);
  prnIFSel    := MagicAES.RsrcGaddr (MagicAES.RTREE, Fredrsc.Ifbox);
  IF ~InitDial (Fredrsc.Prnconf, printConf) THEN RETURN END; 
  prnConf := printConf;
  setGetOpts (TRUE);
  (* Noch Namen des CFG-Files *)
  IF ConfVars.GetConfigString (cPrtCfg, cfgFile)
  THEN
    mtDir.SplitPath (cfgFile, cfgPath, cfgName, cfgExt);
  ELSE
    MagicStrings.Assign ('', cfgFile);
    MagicStrings.Assign ('noname.cfg',cfgName);
    MagicStrings.Assign (homePath,cfgPath);
  END;
  mtUtils.SetObjcString (printConf, Fredrsc.Oselcfg, cfgName);
  MagicAES.WindUpdate (MagicAES.BEGMCTRL);
  mtDials.DialForm (printConf, mtDials.DSTART, v.r, v.r);
  mtDials.DialDraw (printConf, 0, 99, v.r, FALSE);
  LOOP
   but := mtDials.DialDo (printConf, 0);
   but := INTEGER(BITSET(but) - {15});
   CASE but OF
    Fredrsc.Oprtsiz0,
    Fredrsc.Oprtsiz1:
           but := Fredrsc.Oprtsiz1;
           MagicAES.ObjcOffset (printConf, but, x, y);
           t := ADR (prnConf^[but].obState);
           select := mtPopups.TreePopup (prnStyleSel, x, y, ORD(t^.hi))-1;
           IF select >= 0 THEN
             t^.hi := CHR(select);
             SetXString (printConf, but, prnStyleSel, select);
             mtDials.DialDraw (printConf, but, 0, v.r, FALSE);
           END;|
    Fredrsc.Oprtsiz2:
           t := ADR (prnConf^[but-1].obState);
           t^.hi := CHR((ORD(t^.hi)+1) MOD 3);
           select := ORD (t^.hi);
           SetXString (printConf, but-1, prnStyleSel, select);
           mtDials.DialDraw (printConf, but-1, 0, v.r, FALSE); |
    Fredrsc.Ointerfc0,
    Fredrsc.Ointerfc1: 
           but := Fredrsc.Ointerfc1;
           MagicAES.ObjcOffset (printConf, but, x, y);
           t := ADR (prnConf^[but].obState);
           select := mtPopups.TreePopup (prnIFSel, x, y, ORD(t^.hi))-1;
           IF select >= 0 THEN
             t^.hi := CHR(select);
             SetXString (printConf, but, prnIFSel, select);
             mtDials.DialDraw (printConf, but, 0, v.r, FALSE);
           END;|
    Fredrsc.Ointerfc2:
           t := ADR (prnConf^[but-1].obState);
           t^.hi := CHR((ORD(t^.hi)+1) MOD 2);
           select := ORD (t^.hi);
           SetXString (printConf, but-1, prnIFSel, select);
           (*
           mtUtils.ObjcString (prnIFSel, select+1, selStr);
           mtUtils.SetObjcString (printConf, but-1, selStr);
           *)
           mtDials.DialDraw (printConf, but-1, 0, v.r, FALSE); |
    Fredrsc.Oselcfg0,
    Fredrsc.Oselcfg:
           but := Fredrsc.Oselcfg;
           mtDials.DialForm (printConf, mtDials.DDISABLE, v.r, v.r);
           res := CatGlobal.FselGet (cfgPath, cfgName, '*.cfg', 'CFG-Datei ausw„hlen', TRUE);
           mtDials.DialForm (printConf, mtDials.DENABLE, v.r, v.r); 
           IF res & (cfgName[0] # '')
           THEN
             MagicStrings.Assign (cfgPath, cfgFile);
             MagicStrings.Append (cfgName, cfgFile);
             Printer.LoadCFGFile (cfgFile);
             IF Printer.Response = Printer.CFGnotFound
             THEN
               v.int := mtAlerts.Alert (1, cfgNotFound);
             ELSIF Printer.Response = Printer.wrongIdent
             THEN
               v.int := mtAlerts.Alert (1, noCfgFile);
             ELSIF Printer.Response = Printer.done
             THEN
               Printer.GetPrnName (name);
               mtUtils.SetObjcString (printConf, Fredrsc.Oselcfg, cfgName);
               mtUtils.SetObjcString (printConf, Fredrsc.Printname, name);
               mtUtils.CalcArea (printConf, Fredrsc.Printname, v.r);
               mtDials.DialDraw (printConf, 0, 8, v.r, TRUE);
             END;
           ELSIF res
           THEN
             Printer.FreeCFGFile();
             MagicStrings.Assign ('', cfgFile);
             Printer.GetPrnName (name);
             mtUtils.SetObjcString (printConf, Fredrsc.Printname, name);
             MagicStrings.Assign ('noname.cfg',cfgName);
             mtUtils.SetObjcString (printConf, Fredrsc.Oselcfg, cfgName);
             mtUtils.CalcArea (printConf, Fredrsc.Printname, v.r);
             mtDials.DialDraw (printConf, 0, 8, v.r, TRUE);
           END; 
           mtUtils.ExclState (printConf, but, MagicAES.SELECTED);
           mtDials.DialDraw (printConf, but, 0, v.r, FALSE); |  
    Fredrsc.Prok,
    Fredrsc.Prcancel: 
           EXIT; |
   ELSE
   END;
  END;
  IF but = Fredrsc.Prok
  THEN
    setGetOpts (FALSE);
    IF cfgFile[0] # '' THEN v.bool := ConfVars.SetConfigString (cPrtCfg, cfgFile); END;
  ELSE
    ConfVars.GetConfDefStr (cPrtCfg, cfgFile, '');
    IF cfgFile[0] # '' THEN Printer.LoadCFGFile (cfgFile); END;
  END;
  mtUtils.ExclState (printConf, but, MagicAES.SELECTED);
  mtDials.DialForm (printConf, mtDials.DFINISH, v.r, v.r);
  mtDials.DisposeDial (printConf);
  MagicAES.WindUpdate (MagicAES.ENDMCTRL);
END doPrinter;
*)

PROCEDURE makeTmpName (VAR path, name: ARRAY OF CHAR);
 TYPE lBITSET = SET OF [0..31];  
  VAR currentPath: CatTypes.String255;
      tname     : CatTypes.String127;
      mtime,
      sec       : LONGCARD;
BEGIN
  (* Aktuellen Pfad merken *)
  CatFiles.GetPath (currentPath);
  (* TmpDir holen *)
  IF ~mtCommand.EnvVar ('TMP', path)
  THEN
    (* tmpDir ist aktuelles Verzeichnis! *)
    MagicStrings.Assign (currentPath, path);
  END;
  (* Tmp-Pfad setzen *)
  v.bool := CatFiles.SetPath (path);
  (* Dateinamen basteln aus Inhalt des 200 Hz Timers *)
  REPEAT
    mtime := MagicXBIOS.Random();
    MagicStrings.Assign ('CT', tname);
    MagicStrings.Append (StrConv.LNumToStr (mtime, 36, 6, '0'), tname);
    (* Jetzt testen, ob Datei schon vorhanden *)
    MagicStrings.Assign (tname, name);
    sec := CatFiles.FileSize (name, v.bool);
  UNTIL ~v.bool;
  (* Aktuellen Pfad wiederherstellen *)
  v.bool := CatFiles.SetPath (currentPath);
END makeTmpName;

PROCEDURE buildCommand (REF com, path, in, out: ARRAY OF CHAR; VAR cmd : ARRAY OF CHAR);
(* In dieser Prozedur werden haupts„chlich Strings ersetzt 
 * Das eigentliche zusammenbauen der Kommandozeile wird von einer
 * Prozedur weiter oben in der Hierarchie erledigt 
 * Folgendes wird ersetzt: $B f�r Eingabeblock durch ersten Namen (in),
 * $O f�r Ausgabe des Kommandos durch zweiten Namen
 *)
 VAR tname  : CatTypes.String255;
BEGIN
  MagicStrings.Assign (path, tname);
  MagicStrings.Append (in, tname);
  MagicStrings.Assign (com, cmd);
  CatGlobal.ReplaceStr (cmd, '$B', tname);
  MagicStrings.Assign (path, tname);
  MagicStrings.Append (out, tname);
  CatGlobal.ReplaceStr (cmd, '$O', tname);
END buildCommand;

PROCEDURE PipeEditBlock (wdw: INTEGER; REF command: ARRAY OF CHAR);
  VAR path,
      tname,
      inName,
      outName : CatTypes.String255;
      len     : LONGCARD;
      cmdLine : CatTypes.String255;
BEGIN
  (* Vorgehensweise: 2*tmpFileName erstellen (in und out)
   * Kommando mit Redirection an shell absetzen 
   * kommando <in >out
   *)
  makeTmpName (path, inName);
  (* Block aus Editor schreiben *)
  CatEdit.EditSave (wdw, path, inName, FALSE);
  (* zweiten tmpnamen basteln *)
  makeTmpName (path, outName);
  (* Shellkommando basteln *)
  buildCommand (command, path, inName, outName, cmdLine);
  (* Shellkommando aufrufen *)
  ShellCall.CallShell (cmdLine, TRUE);
  (* Testen, ob Ausgabe existiert und l„nger als 0 Bytes ist *)
  MagicStrings.Assign (path, tname);
  MagicStrings.Append (outName, tname);
  len := CatFiles.FileSize (tname, v.bool);
  IF v.bool & (len > 0) 
  THEN
    (* Ausgabe in Editor einlesen *)
    CatEdit.EditPasteFile (wdw, TRUE, path, outName);
  END;
  (* tempor„re Files wieder l”schen *)
  v.bool := CatFiles.DeleteFile (path, inName);
  v.bool := CatFiles.DeleteFile (path, outName);
END PipeEditBlock;

PROCEDURE ProcessFilter (wdw: INTEGER; withDial: BOOLEAN);
  VAR cmd       : CatTypes.String255;
BEGIN
  IF (withDial & doFilter (filterNumber, cmd)) OR
     (~withDial & doPopupFilter (filterNumber, cmd))
  THEN
    IF filterNumber <= 6
    THEN
      CASE filterNumber OF
        0   : CatEdit.BlockRot  (wdw); |
        1   : CatEdit.BlockRot18 (wdw); |
        2   : CatEdit.BlockSwap (wdw); |
        3   : CatEdit.BlockUp   (wdw); |
        4   : CatEdit.BlockDown (wdw); |
        5   : CatEdit.BlockCapitals (wdw); |
        6   : CatEdit.BlockMirror (wdw); |
      ELSE
      END;
    ELSE
      IF LENGTH(cmd) > 0
      THEN
        PipeEditBlock (wdw, cmd);
      END;
    END;
  END;
END ProcessFilter;

PROCEDURE GetOrSetMark (getIt : BOOLEAN; wdw : INTEGER);
VAR exit   : INTEGER;
    str    : ARRAY[0..10] OF CHAR;
    nr: INTEGER;
BEGIN
  IF getIt 
  THEN
    mtUtils.SetObjcString (gotoBox, Fredrsc.Setmark, "Marke anspringen");
  ELSE
    mtUtils.SetObjcString (gotoBox, Fredrsc.Setmark, "Marke setzen");
  END;
  exit    := FormHandle (Fredrsc.Gotobox);
  IF exit # Fredrsc.Mbquit THEN
    IF getIt
    THEN
      CatEdit.ToMark (wdw, exit-Fredrsc.Mb1);
    ELSE
      CatEdit.SetMark (wdw, exit-Fredrsc.Mb1);
    END;
  END;
END GetOrSetMark;

PROCEDURE GetLine (wdw : INTEGER);
VAR exit   : INTEGER;
    str    : ARRAY[0..10] OF CHAR;
    nr: LONGINT;
BEGIN
  mtUtils.SetObjcString (lineBox, Fredrsc.Zeilennr, "");
  exit    := FormHandle (Fredrsc.Linebox);
  IF exit = Fredrsc.Zeileok THEN
    mtUtils.ObjcString (lineBox, Fredrsc.Zeilennr, str);
    v.card := 0;
    nr := StrConv.StrToLInt (str, v.card, v.bool);
    IF v.bool
    THEN
      CatEdit.ToLineNr (wdw, nr);
    END;
  END;
END GetLine;

PROCEDURE GetTabSize (wdw : INTEGER);
VAR exit   : INTEGER;
    str    : ARRAY[0..20] OF CHAR;
    nr: INTEGER;
    redraw: BOOLEAN;
    varname : CatTypes.String127;
    i       : INTEGER;
    isTop   : BOOLEAN;
BEGIN
  (* Box initialisieren *)
  isTop := CatEdit.IsEditTop (wdw);

  mtUtils.SetState (tabBox, Fredrsc.Taext0, MagicAES.DISABLED, ~isTop);
  mtUtils.SetState (tabBox, Fredrsc.Tatabw0, MagicAES.DISABLED, ~isTop);
  mtUtils.SetState (tabBox, Fredrsc.Taumbr0, MagicAES.DISABLED, ~isTop);
  mtUtils.SetState (tabBox, Fredrsc.Tartab0, MagicAES.DISABLED, ~isTop);
  mtUtils.SetState (tabBox, Fredrsc.Taback0, MagicAES.DISABLED, ~isTop);
  mtUtils.SetState (tabBox, Fredrsc.Talinel0, MagicAES.DISABLED, ~isTop);
  mtUtils.SetFlag (tabBox, Fredrsc.Talinel0, MagicAES.EDITABLE, isTop);
  mtUtils.SetFlag (tabBox, Fredrsc.Tatabw0, MagicAES.EDITABLE, isTop);
  IF isTop
  THEN
    (* Erstmal die Topwindow-Sachen *)
    CatEdit.GetTabsize (wdw, nr);
    mtUtils.SetObjcString (tabBox, Fredrsc.Tatabw0, StrConv.IntToStr (nr,0));
    SetItem (tabBox, Fredrsc.Taumbr0, CatEdit.GetMode (wdw, CatEdit.wrapMode));
    SetItem (tabBox, Fredrsc.Taback0, CatEdit.GetMode (wdw, CatEdit.autoBackup));
    SetItem (tabBox, Fredrsc.Tartab0, CatEdit.GetMode (wdw, CatEdit.tabMode));
    CatEdit.GetMargins (wdw, nr);
    mtUtils.SetObjcString (tabBox, Fredrsc.Talinel0, StrConv.IntToStr (nr,0));
  END;
  (* Und jetzt die �ber die Configstrings *)
  FOR i := 1 TO 8 DO
    buildVarName (cExtension, i, varname);
    ConfVars.GetConfDefStr (varname, str, "");
    mtUtils.SetObjcString (tabBox, Fredrsc.Taext1+i-1, str);
    buildVarName (cExtTabsize, i, varname);
    ConfVars.GetConfDefInt (varname, nr, 4);
    mtUtils.SetObjcString (tabBox, Fredrsc.Tatabw1+i-1, StrConv.IntToStr (nr,0));
    buildVarName (cExtHardTabs, i, varname);
    ConfVars.GetConfDefBool (varname, v.bool, FALSE);
    SetItem (tabBox, Fredrsc.Tartab1+i-1, v.bool);
    buildVarName (cExtWordWrap, i, varname);
    ConfVars.GetConfDefBool (varname, v.bool, FALSE);
    SetItem (tabBox, Fredrsc.Taumbr1+i-1, v.bool);
    buildVarName (cExtRightMargin, i, varname);
    ConfVars.GetConfDefInt (varname, nr, 255);
    mtUtils.SetObjcString (tabBox, Fredrsc.Talinel1+i-1, StrConv.IntToStr (nr,0));
    buildVarName (cExtAutoBackup, i, varname);
    ConfVars.GetConfDefBool (varname, v.bool, FALSE);
    SetItem (tabBox, Fredrsc.Taback1+i-1, v.bool);
  END;

  exit    := FormHandle (Fredrsc.Tabbox);
  IF exit = Fredrsc.Tabok THEN

    redraw := FALSE;
    (* Erstmal die Topwindow-Sachen *)
    CatEdit.SetMode (wdw, CatEdit.wrapMode, GetItem (tabBox, Fredrsc.Taumbr0));
    CatEdit.SetMode (wdw, CatEdit.autoBackup, GetItem (tabBox, Fredrsc.Taback0));
    CatEdit.SetMode (wdw, CatEdit.tabMode, GetItem (tabBox, Fredrsc.Tartab0));
    mtUtils.ObjcString (tabBox, Fredrsc.Tatabw0, str);
    v.card := 0;
    nr := StrConv.StrToInt (str, v.card, v.bool);
    IF v.bool
    THEN
      CatEdit.SetTabsize (wdw, nr);
      IF CatEdit.GetMode (wdw, CatEdit.tabMode)
      THEN
        redraw := TRUE;
      END;
    END;
    mtUtils.ObjcString (tabBox, Fredrsc.Talinel0, str);
    v.card := 0;
    nr := StrConv.StrToInt (str, v.card, v.bool);
    IF v.bool
    THEN
      CatEdit.SetMargins (wdw, nr, GetItem (tabBox, Fredrsc.Taumbr0));
      redraw := TRUE;
    END;
    IF redraw
    THEN
      WdwManager.FullRedrawWdw (wdw);
    END;

    (* Und jetzt die �ber die Configstrings *)
    FOR i := 1 TO 8 DO
      mtUtils.ObjcString (tabBox, Fredrsc.Taext1+i-1, str);
      IF str[0] # ''
      THEN
        buildVarName (cExtension, i, varname);
        v.bool := ConfVars.SetConfigString (varname, str);
        mtUtils.ObjcString (tabBox, Fredrsc.Tatabw1+i-1, str);
        v.card := 0;
        nr := StrConv.StrToInt (str, v.card, v.bool);
        IF v.bool
        THEN
          buildVarName (cExtTabsize, i, varname);
          v.bool := ConfVars.SetConfigInt (varname, nr);
        END;
        buildVarName (cExtHardTabs, i, varname);
        v.bool := ConfVars.SetConfigBool (varname, GetItem (tabBox, Fredrsc.Tartab1+i-1));
        buildVarName (cExtWordWrap, i, varname);
        v.bool := ConfVars.SetConfigBool (varname, GetItem (tabBox, Fredrsc.Taumbr1+i-1));
        mtUtils.ObjcString (tabBox, Fredrsc.Talinel1+i-1, str);
        v.card := 0;
        nr := StrConv.StrToInt (str, v.card, v.bool);
        IF v.bool
        THEN
          buildVarName (cExtRightMargin, i, varname);
          v.bool := ConfVars.SetConfigInt (varname, nr);
        END;
        buildVarName (cExtAutoBackup, i, varname);
        v.bool := ConfVars.SetConfigBool (varname, GetItem (tabBox, Fredrsc.Taback1+i-1));
      END;
    END;
  END;
END GetTabSize;

PROCEDURE GetRightMargin (wdw : INTEGER);
VAR exit   : INTEGER;
    str    : ARRAY[0..10] OF CHAR;
    nr     : INTEGER;
    umbr   : BOOLEAN;
BEGIN
  SetItem (umbruchBox, Fredrsc.Umbruchan, CatEdit.GetMode (wdw, CatEdit.wrapMode));
  CatEdit.GetMargins (wdw, nr);
  mtUtils.SetObjcString (umbruchBox, Fredrsc.Uspalte, StrConv.IntToStr (nr,0));
  exit    := FormHandle (Fredrsc.Umbruch);
  IF exit = Fredrsc.Umbrok THEN
    mtUtils.ObjcString (umbruchBox, Fredrsc.Uspalte, str);
    v.card := 0;
    nr := StrConv.StrToInt (str, v.card, v.bool);
    umbr := GetItem (umbruchBox, Fredrsc.Umbruchan);
    IF v.bool OR ~umbr
    THEN
      IF umbr
      THEN
        CatEdit.SetMargins (wdw, nr, umbr);
      ELSE
        CatEdit.SetMargins (wdw, maxLineLength, umbr);
      END;
      WdwManager.FullRedrawWdw (wdw);
    END;
  END;
END GetRightMargin;

PROCEDURE doShortBox ();
  VAR exit : INTEGER;
      path : MaxStr;
      name : ARRAY [0..40] OF CHAR;
BEGIN
  (* String setzen *)
  IF shortFileRead 
  THEN
    FileNames.SplitPath (lastShort, path, name);
  ELSE
    Strings.Assign ('', name, v.bool);
  END;
  mtUtils.SetObjcString (shortBox, Fredrsc.Sbinfo, name);
  exit    := FormHandle (Fredrsc.Shortbox);
  IF exit = Fredrsc.Sbkill
  THEN
    CatEdit.FreeShortkeyList();
    shortFileRead := FALSE;
    ConfVars.DeleteConfigVar (cShortFile);
  ELSIF exit = Fredrsc.Sbload
  THEN
    FileNames.SplitPath (lastShort, path, name);
    IF FselGet(path, name, '*.krz', 'K�rzeldatei laden', FALSE)
    THEN
      Strings.Assign (path, lastShort, v.bool);
      Strings.Append (name, lastShort, v.bool);
      CatEdit.ReadShortkeyFile (lastShort);
      v.bool := ConfVars.SetConfigString (cShortFile, lastShort);
      shortFileRead := TRUE;
    END;
  END;
END doShortBox;

PROCEDURE doFileInfos (wdw : INTEGER);
  VAR lines, bytes, totalMem : LONGCARD;
      exit, edits : INTEGER;
      fname : ARRAY [0..20] OF CHAR;
BEGIN
  IF CatEdit.FileInfos (wdw, lines, bytes, edits, totalMem, fname)
  THEN
    (* Parameter setzen *)
    mtUtils.SetObjcString (infoBox, Fredrsc.Finame, fname);
    mtUtils.SetObjcString (infoBox, Fredrsc.Fisize, StrConv.CardToStr(bytes,0));
    mtUtils.SetObjcString (infoBox, Fredrsc.Fiusedm, StrConv.CardToStr(totalMem,0));
    mtUtils.SetObjcString (infoBox, Fredrsc.Filines, StrConv.CardToStr (lines,0));
    mtUtils.SetObjcString (infoBox, Fredrsc.Fifiles, StrConv.IntToStr (edits,0));
    mtUtils.SetObjcString (infoBox, Fredrsc.Fimem, StrConv.CardToStr (MemAvail(),0));
    (* Box aufrufen *)
    exit := FormHandle (Fredrsc.Fileinfo);
  END;
END doFileInfos;


TYPE floskelArray =  ARRAY [1..20] OF ARRAY[0..511] OF CHAR;

     floskelInfo = RECORD
                     txtArray : POINTER TO floskelArray;
                     oldEntry : INTEGER;
                     oldShift : BOOLEAN;
                     theWdw   : INTEGER;
                   END;
    floskelPtr = POINTER TO floskelInfo;
    
  PROCEDURE SetStrings (tree: ADDRESS; from, to : INTEGER; REF string : ARRAY OF CHAR);
    VAR i         : INTEGER;
        entryLen  : INTEGER;
        obIdx     : INTEGER;
        str       : ARRAY [0..79] OF CHAR;
  BEGIN
    (* Alle Textfelder l”schen *)
    FOR i := from TO to DO
      mtUtils.SetObjcString (tree, i, '');
    END;
    i := 0;
    obIdx := from;
    WHILE (i < INTEGER(LENGTH (string))) & (obIdx <= to) DO
      mtUtils.ObjcStrLen (tree, obIdx, entryLen, v.int);
      DEC (entryLen, 4);
      MagicStrings.Copy (string, i, entryLen-1, str);
      mtUtils.SetObjcString (tree, obIdx, str);
      INC (obIdx);
      INC (i, entryLen-1);
    END;
  END SetStrings;

  PROCEDURE SetEntry (tree: ADDRESS; floskel : floskelPtr;
                      idx : INTEGER; isShift : BOOLEAN);
    VAR i       : INTEGER;
        str     : ARRAY  [0..1023] OF CHAR;
        strIdx    : INTEGER;
  BEGIN
    strIdx := idx - Fredrsc.Fl_f1 + 1;
    IF isShift THEN INC (strIdx, 10) END;
    (* Suchen nach einzelnen LFs und ersetzen davon *)
    Strings.Assign (floskel^.txtArray^[strIdx], str, v.bool);
    i := 0;
    WHILE i >= 0 DO
      i := Strings.Pos (LF, str, i);
      IF i >= 0
      THEN
        Strings.Delete (str, i, 1, v.bool);
      END;
    END;
    CatGlobal.SetStrings (tree, Fredrsc.Flline1, Fredrsc.Flline6, str);
  END SetEntry;
  
  PROCEDURE GetEntry (tree: ADDRESS; floskel : floskelPtr;
                      idx : INTEGER; isShift : BOOLEAN);
    VAR i       : INTEGER;
        str     : ARRAY  [0..1023] OF CHAR;
        strIdx  : INTEGER;
  BEGIN 
    strIdx := idx - Fredrsc.Fl_f1 + 1;
    IF isShift THEN INC (strIdx, 10) END;
    CatGlobal.GetStrings (tree, Fredrsc.Flline1, Fredrsc.Flline6, floskel^.txtArray^[strIdx]);
    i := 0; 
    (* Suchen nach einzelnen CRs und diese ersetzen durch Cr/LF *)
    Strings.Assign (floskel^.txtArray^[strIdx], str, v.bool);
    WHILE i >= 0 DO
      i := Strings.Pos (CR, str, i);
      IF i >= 0
      THEN
        IF str[i+1] # LF
        THEN
          Strings.Insert (LF, i+1, str, v.bool);
        END;
        INC (i);
      END;
    END;
    (* Suchen nach einzelnen LFs und ersetzen davon *)
    i := 0;
    WHILE i >= 0 DO
      i := Strings.Pos (LF, str, i);
      IF i >= 0
      THEN
        IF (i=0) OR ((i > 0) & (str[i-1] # CR))
        THEN
          Strings.Insert (CR, i, str, v.bool);
        END;
        INC (i);
      END;
    END;
    (* Jetzt nur noch in Textarray sichern *)
    Strings.Assign (str, floskel^.txtArray^[strIdx], v.bool);
  END GetEntry;

PROCEDURE floskelButton (tree: ADDRESS; private: ADDRESS; button: INTEGER;
                         mx, my : INTEGER; kstate: BITSET; clicks: INTEGER): BOOLEAN;
  VAR   floskel : floskelPtr;
        but     : INTEGER;
        isShift: BOOLEAN;
        strPtr  : CatTypes.Str1023Ptr;
        strLen  : LONGCARD;
BEGIN
  floskel := private;
  but := INTEGER(BITSET(button) - {15});
  CASE but OF
    Fredrsc.Fl_f1..Fredrsc.Fl_f10 :
      GetEntry (tree, floskel, floskel^.oldEntry, floskel^.oldShift);
      isShift := mtUtils.InState (tree, Fredrsc.Fl_shift, MagicAES.SELECTED);
      SetEntry (tree, floskel, but, isShift);
      floskel^.oldShift := isShift;
      floskel^.oldEntry   := but; 
      WinDials.WinDialDraw (tree, Fredrsc.Flbox, 2, v.r, FALSE);
      |
    Fredrsc.Fl_shift: 
      GetEntry (tree, floskel, floskel^.oldEntry, floskel^.oldShift);
      isShift := mtUtils.InState (tree, Fredrsc.Fl_shift, MagicAES.SELECTED);
      SetEntry (tree, floskel, floskel^.oldEntry, isShift);
      floskel^.oldShift := isShift;
      WinDials.WinDialDraw (tree , Fredrsc.Flbox, 2, v.r, FALSE);
      |
    Fredrsc.Flblock:
      IF CatEdit.GetBlock (floskel^.theWdw, FALSE, TRUE, strPtr, strLen)
      THEN
        IF strLen > 512 THEN strPtr^[511] := 0C END;
        CatGlobal.SetStrings (tree, Fredrsc.Flline1, Fredrsc.Flline6, strPtr^);
        GetEntry (tree, floskel, floskel^.oldEntry, floskel^.oldShift);
        SetEntry (tree, floskel, floskel^.oldEntry, floskel^.oldShift);
        WinDials.WinDialDraw (tree , Fredrsc.Flbox, 2, v.r, FALSE);
        DEALLOCATE (strPtr, 0);
        mtUtils.ExclState (tree, but, MagicAES.SELECTED);
        WinDials.WinDialDraw (tree, but, 0, v.r, FALSE);
      END;
      |
    Fredrsc.Flok,
    Fredrsc.Flcancel:
      mtUtils.ExclState (tree, but, MagicAES.SELECTED);
      GetEntry (tree, floskel, floskel^.oldEntry, floskel^.oldShift);
      RETURN TRUE; |
  ELSE
  END;
  RETURN FALSE;
END floskelButton;

PROCEDURE floskelGetSetValues (tree: ADDRESS; private: ADDRESS; 
                               set: BOOLEAN; exit: INTEGER);
  VAR   floskel : floskelPtr;
        i       : INTEGER;
        found   : BOOLEAN;
        isShift: BOOLEAN;
        str     : ARRAY [0..511] OF CHAR;
        varName : CatTypes.String127;
        but     : INTEGER;
BEGIN
  floskel := private;
  but := INTEGER(BITSET(exit) - {15});
  IF set
  THEN
    FOR i := 1 TO 10 DO 
      buildVarName (cNormalFkey, i, varName);
      ConfVars.GetConfDefStr (varName, floskel^.txtArray^[i], '');
    END;
    mtUtils.SetState (tree, Fredrsc.Flblock, MagicAES.DISABLED, 
                      ~(CatEdit.IsEditTop (floskel^.theWdw) & 
                        CatEdit.BlockIsMarked (floskel^.theWdw)));
    FOR i := 1 TO 10 DO 
      buildVarName (cShiftFkey, i, varName);
      ConfVars.GetConfDefStr (varName, floskel^.txtArray^[10+i], '');
    END;
    (* Selektierten Eintrag feststellen *)
    i := Fredrsc.Fl_f1;
    found := FALSE;
    WHILE ~found & (i <= Fredrsc.Fl_f10) DO
      found := mtUtils.InState (tree, i, MagicAES.SELECTED);
      IF ~found THEN INC (i); END;
    END;
    isShift := mtUtils.InState (tree, Fredrsc.Fl_shift, MagicAES.SELECTED);
    SetEntry (tree, floskel, i, isShift);
    floskel^.oldEntry := i; 
    floskel^.oldShift := isShift;
  ELSE
    IF but = Fredrsc.Flok
    THEN
      (* Strings abspeichern *)
      FOR i := 1 TO 10 DO 
        buildVarName (cNormalFkey, i, varName);
        IF ConfVars.GetConfigString (varName, str) OR (LENGTH (floskel^.txtArray^[i]) > 0) THEN
          v.bool := ConfVars.SetConfigString (varName, floskel^.txtArray^[i]);
        END;
      END;
      FOR i := 1 TO 10 DO 
        buildVarName (cShiftFkey, i, varName);
        IF ConfVars.GetConfigString (varName, str) OR (LENGTH (floskel^.txtArray^[10+i]) > 0) THEN
          v.bool := ConfVars.SetConfigString (varName, floskel^.txtArray^[10+i]);
        END;
      END;
    END;
    DEALLOCATE (floskel^.txtArray, 0);
    DISPOSE (floskel);
  END;
END floskelGetSetValues;

PROCEDURE doFloskel();
  VAR floskelBox: mtUtils.tObjcTree;
      floskel   : floskelPtr;
BEGIN
  (* vorbereiten *)
  floskelBox := MagicAES.RsrcGaddr(MagicAES.RTREE, Fredrsc.Floskeln);
  NEW (floskel);
  IF floskel = NIL
  THEN
    RETURN
  END;
  ALLOCATE (floskel^.txtArray, TSIZE (floskelArray));
  IF floskel^.txtArray = NIL
  THEN
    DISPOSE (floskel);
    RETURN
  END; 
  floskel^.theWdw := WdwManager.theTopWindow;
  IF ~WinDials.OpenWinDial (floskelBox, FALSE, 
                            floskelGetSetValues,
                            floskelGetSetValues,
                            floskelButton,
                            WinDials.defDraw,
                            "",
                            floskel)
  THEN
    noWinDialAlert();
    DEALLOCATE (floskel^.txtArray, 0);
    DISPOSE (floskel);
  END;
END doFloskel;

(*
PROCEDURE doFloskelDialogue();
  TYPE floskelArray =  ARRAY [1..20] OF ARRAY[0..511] OF CHAR;
  VAR txtArray  : POINTER TO floskelArray;
      str       : ARRAY [0..511] OF CHAR;
  
  PROCEDURE SetStrings (REF string : ARRAY OF CHAR);
     VAR i       : INTEGER;
        entryLen  : INTEGER;
        obIdx   : INTEGER;
  BEGIN
    (* Alle Textfelder l”schen *)
    FOR i := Fredrsc.Flline1 TO Fredrsc.Flline6 DO
      mtUtils.SetObjcString (floskelBox, i, '');
    END;
    i := 0;
    obIdx := Fredrsc.Flline1;
    WHILE (i < INTEGER(LENGTH (string))) & (obIdx <= Fredrsc.Flline6) DO
      mtUtils.ObjcStrLen (floskelBox, obIdx, entryLen, v.int);
      Strings.Copy (string, i, entryLen-1, str, v.bool);
      mtUtils.SetObjcString (floskelBox, obIdx, str);
      INC (obIdx);
      INC (i, entryLen-1);
    END;
  END SetStrings;
    
  PROCEDURE SetEntry (idx : INTEGER; isShift : BOOLEAN);
    VAR strIdx    : INTEGER;
  BEGIN
    strIdx := idx - Fredrsc.Fl_f1 + 1;
    IF isShift THEN INC (strIdx, 10) END;
    SetStrings (txtArray^[strIdx]);
  END SetEntry;
  
  PROCEDURE GetEntry (idx : INTEGER; isShift : BOOLEAN);
    VAR i       : INTEGER;
        str     : ARRAY  [0..511] OF CHAR;
        strIdx  : INTEGER;
  BEGIN 
    strIdx := idx - Fredrsc.Fl_f1 + 1;
    IF isShift THEN INC (strIdx, 10) END;
    txtArray^[strIdx] := '';
    FOR i := Fredrsc.Flline1 TO Fredrsc.Flline6 DO
      mtUtils.ObjcString (floskelBox, i, str);
      Strings.Append (str, txtArray^[strIdx], v.bool);
    END;
  END GetEntry;

VAR
      i         : INTEGER;
      found, 
      isShift   : BOOLEAN;
      varName   : ARRAY [0..39] OF CHAR;
      but       : INTEGER;
      oldShift  : BOOLEAN;
      oldEntry  : INTEGER;
      strLen    : LONGCARD;
      strPtr    : POINTER TO ARRAY [0..1023] OF CHAR;
BEGIN
  (* vorbereiten *)
  IF ~InitDial (Fredrsc.Floskeln, floskelBox)
  THEN
    RETURN 
  END;
  ALLOCATE (txtArray, TSIZE (floskelArray));
  IF txtArray = NIL
  THEN
    EditFuncs.OutOfMem();
  END; 
  FOR i := 1 TO 10 DO 
    Strings.Assign (cNormalFkey, varName, v.bool);
    Strings.Append (StrConv.IntToStr (i,0), varName, v.bool);
    ConfVars.GetConfDefStr (varName, txtArray^[i], '');
  END;
  mtUtils.SetState (floskelBox, Fredrsc.Flblock, MagicAES.DISABLED, 
                    ~(CatEdit.IsEditTop (WdwManager.theTopWindow) & 
                      CatEdit.BlockIsMarked (WdwManager.theTopWindow)));
  FOR i := 1 TO 10 DO 
    Strings.Assign (cShiftFkey, varName, v.bool);
    Strings.Append (StrConv.IntToStr (i,0), varName, v.bool);
    ConfVars.GetConfDefStr (varName, txtArray^[10+i], '');
  END;
  (* Selektierten Eintrag feststellen *)
  i := Fredrsc.Fl_f1;
  found := FALSE;
  WHILE ~found & (i <= Fredrsc.Fl_f10) DO
    found := mtUtils.InState (floskelBox, i, MagicAES.SELECTED);
    IF ~found THEN INC (i); END;
  END;
  isShift := mtUtils.InState (floskelBox, Fredrsc.Fl_shift, MagicAES.SELECTED);
  SetEntry (i, isShift);
  oldEntry := i; 
  oldShift := isShift;
  mtDials.DialForm (floskelBox, mtDials.DSTART, v.r, v.r);
  mtDials.DialDraw (floskelBox, 0, 99, v.r, FALSE);
  LOOP
    but := mtDials.DialDo (floskelBox, 0);
    but := INTEGER(BITSET(but) - {15});
    CASE but OF
      Fredrsc.Fl_f1..Fredrsc.Fl_f10:
        GetEntry (oldEntry, oldShift);
        isShift := mtUtils.InState (floskelBox, Fredrsc.Fl_shift, MagicAES.SELECTED);
        SetEntry (but, isShift);
        oldShift := isShift;
        oldEntry   := but; 
        mtDials.DialDraw (floskelBox, Fredrsc.Flbox, 2, v.r, FALSE);
        |
      Fredrsc.Fl_shift:
        GetEntry (oldEntry, oldShift);
        isShift := mtUtils.InState (floskelBox, Fredrsc.Fl_shift, MagicAES.SELECTED);
        oldShift := isShift;
        SetEntry (oldEntry, isShift);
        mtDials.DialDraw (floskelBox , Fredrsc.Flbox, 2, v.r, FALSE);
        |
      Fredrsc.Flblock:
        v.bool := CatEdit.GetBlock (WdwManager.theTopWindow, TRUE, strPtr, strLen);
        IF strLen > 512 THEN strPtr^[511] := 0C END;
        SetStrings (strPtr^);
        GetEntry (oldEntry, oldShift);
        SetEntry (oldEntry, oldShift);
        mtDials.DialDraw (floskelBox , Fredrsc.Flbox, 2, v.r, FALSE);
        DEALLOCATE (strPtr, 0);
        mtUtils.ExclState (floskelBox, but, MagicAES.SELECTED);
        mtDials.DialDraw (floskelBox, but, 0, v.r, FALSE);
        |
      Fredrsc.Flok,
      Fredrsc.Flcancel:
        GetEntry (oldEntry, oldShift);
        EXIT |
    ELSE
    END;
  END;
  IF but = Fredrsc.Flok
  THEN
    (* Strings abspeichern *)
    FOR i := 1 TO 10 DO 
      Strings.Assign (cNormalFkey, varName, v.bool);
      Strings.Append (StrConv.IntToStr (i,0), varName, v.bool);
      IF ConfVars.GetConfigString (varName, str) OR (LENGTH (txtArray^[i]) > 0) THEN
        v.bool := ConfVars.SetConfigString (varName, txtArray^[i]);
      END;
    END;
    FOR i := 1 TO 10 DO 
      Strings.Assign (cShiftFkey, varName, v.bool);
      Strings.Append (StrConv.IntToStr (i,0), varName, v.bool);
      IF ConfVars.GetConfigString (varName, str) OR (LENGTH (txtArray^[10+i]) > 0) THEN
        v.bool := ConfVars.SetConfigString (varName, txtArray^[10+i]);
      END;
    END;
  END;
  mtUtils.ExclState (floskelBox, but, MagicAES.SELECTED);
  mtDials.DialForm (floskelBox, mtDials.DFINISH, v.r, v.r);
  DEALLOCATE (txtArray, 0);
  mtDials.DisposeDial (floskelBox);
END doFloskelDialogue;
*)

PROCEDURE DoAbout;
BEGIN
  v.int := FormHandle(Fredrsc.Aboutbox);
(*   IF v.int = Fredrsc.ainfo THEN v.int := FormHandle(info) END; *)
END DoAbout;

PROCEDURE doErrorBox;
  VAR errName : CatTypes.String255;
BEGIN
  ConfVars.GetConfDefStr (cErrExtension, errName, '');
  ConfVars.GetConfDefStr (cErrMask, errMask, '');
  mtUtils.SetObjcString (errorBox, Fredrsc.Efname, errName);
  mtUtils.SetObjcString (errorBox, Fredrsc.Emask, errMask);
  IF FormHandle(Fredrsc.Errbox) = Fredrsc.Eok
  THEN
    mtUtils.ObjcString (errorBox, Fredrsc.Efname, errName);
    mtUtils.ObjcString (errorBox, Fredrsc.Emask, errMask);
    v.bool := ConfVars.SetConfigString (cErrExtension, errName);
    v.bool := ConfVars.SetConfigString (cErrMask, errMask);
  END;
END doErrorBox;

PROCEDURE ClearScreen();
BEGIN
  MagicDOS.Cconout(33C); MagicDOS.Cconout('E');
END ClearScreen;

PROCEDURE ClearBuffer(e : BITSET; force : BOOLEAN; ks: BITSET; sc: INTEGER; char: CHAR);
  VAR kstate : BITSET;
      scan   : INTEGER;
      ch     : CHAR;
BEGIN
  IF MagicAES.MUKEYBD IN e THEN
    REPEAT
      e := MagicAES.EvntMulti(
               {MagicAES.MUKEYBD, MagicAES.MUTIMER},
                0,{},{}, 0,dr, 0,dr, mScrap, 0,0,
                v.int, v.int, v.bset, v.int, kstate, scan, ch, v.int);
    UNTIL ~(MagicAES.MUKEYBD IN e) OR (CAP(char) IN CatTypes.charSet{'A'..'Z','0'..'9'}) 
        OR (~force & ((ks#kstate) OR (scan # sc)));
    IF MagicAES.MUKEYBD IN e
    THEN
      PushKey (kstate, CHR(scan), ch);
    END;
  END;
END ClearBuffer;


VAR shellCommand : ARRAY[0..65] OF CHAR;

PROCEDURE DoShell();
  VAR j : INTEGER;
BEGIN
  mtUtils.SetObjcString(systemBox, Fredrsc.Sysstr, shellCommand);
  IF FormHandle(Fredrsc.Systembx) # Fredrsc.Sysabruc THEN
    mtUtils.ObjcString(systemBox, Fredrsc.Sysstr, shellCommand);
    IF shell = ShellCall.shellP
    THEN
      mtAppl.MouseOff;
      ClearScreen();
      MagicAES.WindUpdate(MagicAES.ENDUPDATE);
    END;
    ShellCall.CallShell(shellCommand, FALSE);
    IF shell = ShellCall.shellP
    THEN
      MagicAES.WindUpdate(MagicAES.BEGUPDATE);
      MagicDOS.Cconout(CR); MagicDOS.Cconout(LF);
      MagicDOS.Cconws('- Taste dr�cken -');
      ClearBuffer({MagicAES.MUKEYBD}, TRUE, {}, 0, 0C);
      MagicAES.EvntKeybd(v.int, v.int, v.char);
      MagicDOS.Cconws(33C+'f'+0C);        (* Cursor ausschalten *)
      mtAppl.MouseArrow;

      MagicAES.FormDial(MagicAES.FMDFINISH, null, EditTypes.deskSize);
      v.int := MagicAES.MenuBar(menu, MagicAES.Set);
    END;

  ELSE
    mtUtils.SetObjcString(systemBox, Fredrsc.Sysstr, shellCommand);
  END;
END DoShell;

PROCEDURE DoSelectFont (wdw : INTEGER);
 VAR hdl : INTEGER;
     font, size : INTEGER;
     fInfo      : FontSelect.tFontinfo;
     name       : ARRAY [0..45] OF CHAR;
BEGIN
  IF CatEdit.IsEditTop (wdw)
  THEN
    CatEdit.GetEditVDIHandle (wdw, hdl);
    font := FontSelect.FontActive (hdl);
    FontSelect.FontInfo (hdl, font, fInfo);
    size := fInfo.point;
    IF FontSelect.DoSelectFont (hdl, FALSE, font, size)
    THEN
      CatEdit.SelectEditFont (wdw, font, size);
    END;
  END;
END DoSelectFont;

PROCEDURE hdlComp (item, wdw : INTEGER);
  VAR isSaved : BOOLEAN;
      val     : ARRAY [0..511] OF CHAR;
BEGIN
  IF item = Fredrsc.Pcompile
  THEN 
    IF mm2shell
    THEN
      CatEdit.CompileText (wdw);
    ELSE
      (* Filenamen von TopWindow erfragen *)
      IF CatEdit.GetCompInfo (wdw, val, isSaved)
      THEN
        IF ~isSaved THEN 
          CatEdit.AskForSave (wdw);
        END;
        SendEsMessage (SEProto.ES_COMPILE, ADR(val));
      END;
    END;
  ELSE
    CatEdit.EditSave (wdw,'','', FALSE);
    quitProg := CatEdit.CloseAllEditors(FALSE);
    CASE item OF
      Fredrsc.Pcompend : termCode := 1 |
      Fredrsc.Pcomprun : termCode := 2 |
      Fredrsc.Pmake    : termCode := 3 |
      Fredrsc.Pmakerun : termCode := 4 |
    ELSE
    END;
  END;
END hdlComp;

PROCEDURE OpenEditor (REF path, name: ARRAY OF CHAR; VAR wdw: INTEGER; isErrFile: BOOLEAN): BOOLEAN; FORWARD;

PROCEDURE ParseErrLine (REF error, mask: ARRAY OF CHAR;
                        VAR errFile, errMess: ARRAY OF CHAR;
                        VAR errLine: LONGINT; VAR errRow : INTEGER): BOOLEAN;
VAR pIdx, 
    erIdx, elIdx,
    efIdx, emIdx : INTEGER;
    i, j, l      : INTEGER;
    searchPat    : Find2.tpPattern;
    ptrPatt      : Find2.tpPat;
    eIdx,
    sIdx         : INTEGER;
    pattern,
    eLine        : CatTypes.String255;
    numStr       : CatTypes.String127;
    found        : BOOLEAN;

BEGIN
  (* Zuerst bauen wir aus der Maske einen Suchstring auf, indem die 
   * einzelnen Felder durch Wildcards ersetzt werden
   * Damit das auch am Anfang und Ende des Strings funktioniert, wird dann
   * in den �bergebenen String am Anfang ein Control-Zeichen eingef�gt und
   * am Ende auch eines.
   *)
  (* Initialisierung *)
  MagicStrings.Assign ("", errFile);
  MagicStrings.Assign ("", errMess);
  errLine := -1;
  errRow := 0;
  (* Suchmuster aufbauen *)
  i := 0; j := 0;
  l := LENGTH (mask);
  pIdx := 0;
  efIdx := -1; elIdx := -1;
  emIdx := -1; erIdx := -1;
  WHILE i < l DO
    IF (mask[i] = '$') & (mask[i+1] IN  CatTypes.charSet {'F','L','M','R'})
    THEN
      CASE mask[i+1] OF
        'F' : efIdx := pIdx; |
        'L' : elIdx := pIdx; |
        'M' : emIdx := pIdx; |
        'R' : erIdx := pIdx; 
      ELSE
      END;
      INC (pIdx);
      pattern[j] := '*';
      INC (i); (* da i+1 schon ausgewertet wurde *)
    ELSE
      IF mask[i] = '*' THEN INC (pIdx); END;
      pattern[j] := mask[i];
    END;
    INC (j);
    INC (i);
  END;
  pattern[j] := 0C;
  (* Jetzt die �bergebene Zeile kopieren und dann suchen *)
  MagicStrings.Assign (error, eLine);
  (* Steuerzeichen am Ende von error l”schen *)
  l := LENGTH (eLine) - 1;
  WHILE (l >= 0) & ((eLine[l] = 12C) OR (eLine[l] = 15C)) DO
    DEC (l);
  END;
  eLine[l+1] := 0C;
  (* Jetzt eigene Steuerzeichen einf�gen *)
  MagicStrings.Insert (34C, pattern, 0);
  MagicStrings.Append (35C, pattern);
  MagicStrings.Insert (34C, eLine, 0);
  MagicStrings.Append (35C, eLine);
  (* Jetzt das Suchmuster compilieren *)
  
  searchPat := Find2.Compile (pattern, '?', 1C, '*', 35C, TRUE, FALSE);
  (* Jetzt suchen *)
  found := Find2.Find (ADR (eLine), LENGTH (eLine), searchPat, 0);
  IF found
  THEN
    (* Gefunden, jetzt auswerten *)
    eIdx := -1;
    sIdx := -1;
    pIdx := 0;
    ptrPatt := searchPat^.pFirst;
    WHILE ptrPatt # NIL DO
      IF sIdx >= 0
      THEN
        eIdx := SHORT(LONGINT(ADDRESS(ptrPatt^.pMatch)-ADR(eLine)));
        IF pIdx = efIdx
        THEN
          (* Filename *)
          Strings.Copy (eLine, sIdx, eIdx - sIdx, errFile, v.bool);
        ELSIF pIdx = elIdx
        THEN
          Strings.Copy (eLine, sIdx, eIdx - sIdx, numStr, v.bool);
          v.card := 0;
          errLine := StrConv.StrToLInt (numStr, v.card, v.bool);
        ELSIF pIdx = emIdx
        THEN
          Strings.Copy (eLine, sIdx, eIdx - sIdx, errMess, v.bool);
        ELSIF pIdx = erIdx
        THEN
          Strings.Copy (eLine, sIdx, eIdx - sIdx, numStr, v.bool);
          v.card := 0;
          errRow := StrConv.StrToInt (numStr, v.card, v.bool);
        END;
        INC (pIdx);
      END;
      sIdx := SHORT(LONGINT(ADDRESS(ptrPatt^.pMatch)-ADR(eLine))) + ptrPatt^.len;
      ptrPatt :=ptrPatt^.pNext;
    END;
  END;
  Find2.Dispose (searchPat);
  RETURN found;
END ParseErrLine;

PROCEDURE handleErrorLine (wdw: INTEGER; REF error: ARRAY OF CHAR);
  VAR errF : CatTypes.String255;
      errMess:  CatTypes.String255;
      errLine: LONGINT;
      errRow : INTEGER;
      errWdw : INTEGER;
      i      : INTEGER;
      path, 
      name   : CatTypes.String255;
BEGIN
  i := 0;
  WHILE (i < errIndex) & (errFiles[i].wdw # wdw) DO INC (i) END;
  IF (i < errIndex) & 
     ParseErrLine (error, errMask, errF, errMess, errLine, errRow)
  THEN
    IF (LENGTH (errF) > 0) & CatEdit.FileIsEditor (errF, errWdw)
    THEN
      WdwManager.TopWindow (errWdw);
      CatEdit.SetError (errWdw, errLine, errRow, errMess, TRUE);
    ELSE
      IF LENGTH (errF) > 0
      THEN
        FileNames.SplitPath (errF, path, name);
        IF OpenEditor (path, name, errWdw, FALSE)
        THEN
          CatEdit.SetError (errWdw, errLine, errRow, errMess, TRUE);
        END;
      ELSE
        (* Kein File spezifiziert, in dem der Fehler auftrat. 
         * Das erstbeste Fenster nehmen
         *)
        WdwManager.GetOwnTopWindow (errWdw);
        IF ((errWdw # wdw) OR WdwManager.GetSecondWdw (errWdw))
           & CatEdit.IsEditTop (errWdw)
        THEN
          WdwManager.TopWindow (errWdw);
          CatEdit.SetError (errWdw, errLine, errRow, errMess, TRUE);
        END;
      END;
    END;
  END;
END handleErrorLine;

PROCEDURE hdlClose (wdw: INTEGER): BOOLEAN;
  VAR i, j : INTEGER;
BEGIN
  i := 0;
  WHILE (i < errIndex) & (errFiles[i].wdw # wdw) DO INC (i) END;
  IF i < errIndex 
  THEN
    FOR j := i+1 TO errIndex - 1 DO
      errFiles[j-1] := errFiles[j];
    END;
    DEC (errIndex);
  END;
  RETURN TRUE;
END hdlClose;

PROCEDURE OpenEditor (REF path, name: ARRAY OF CHAR; VAR wdw: INTEGER;
                      isErrFile: BOOLEAN): BOOLEAN;
  VAR i     : INTEGER;
      found : BOOLEAN;
      fname     : CatTypes.String255;
      varname   : CatTypes.String127;
      ext       : ARRAY [0..20] OF CHAR;
      tabs,
      margin    : INTEGER;
      succ,
      rtabs,
      wrap,
      errmode,
      doback    : BOOLEAN;
BEGIN
  (* Erstmal nachsehen, ob der Name auf eine der Extensions pažt *)
  i := 0; found := FALSE;
  Strings.Assign (name, fname, v.bool);
  Strings.Upper (fname);
  ConfVars.GetConfDefStr (cErrExtension, ext, '*.err');
  IF (WildCards.MatchName (fname, ext, TRUE) & (errIndex < maxErrFiles))
    OR isErrFile
  THEN
    tabs := 4; rtabs := TRUE;
    wrap := FALSE; margin := 255;
    doback := FALSE;
    errmode := TRUE;
  ELSE
    errmode := FALSE;
    WHILE (i <= 8) & ~found DO
      INC (i);
      buildVarName (cExtension, i, varname);
      IF ConfVars.GetConfigString (varname, ext) & (ext[0] # '')
      THEN
        found := WildCards.MatchName (fname, ext, TRUE)
      END;
    END;
    IF found
    THEN
      (* Ein paar Einstellung holen *)
      buildVarName (cExtTabsize, i, varname);
      ConfVars.GetConfDefInt (varname, tabs, 4);
      buildVarName (cExtHardTabs, i, varname);
      ConfVars.GetConfDefBool (varname, rtabs, FALSE);
      buildVarName (cExtWordWrap, i, varname);
      ConfVars.GetConfDefBool (varname, wrap, FALSE);
      buildVarName (cExtRightMargin, i, varname);
      ConfVars.GetConfDefInt (varname, margin, 255);
      buildVarName (cExtAutoBackup, i, varname);
      ConfVars.GetConfDefBool (varname, doback, FALSE);
    ELSE
      tabs := 4; rtabs := FALSE;
      wrap := FALSE; margin := 255;
      doback := FALSE;
    END;
  END;
  succ:= CatEdit.OpenEditor (path, name, FALSE, 
                             FALSE, NIL, NIL, NIL, ADDRESS(hdlClose), NIL, NIL, NIL, NIL, 
                             margin, TRUE, wrap, -1,
                             wdw);
  IF succ
  THEN
    CatEdit.SetMode (wdw, CatEdit.tabMode, rtabs);
    CatEdit.SetTabsize (wdw, tabs);
    CatEdit.SetMode (wdw, CatEdit.autoBackup, doback);
    IF errmode
    THEN
      v.bool := CatEdit.SetListProc (wdw, ADDRESS(handleErrorLine));
      CatEdit.SetListMode (wdw);
      IF errIndex < maxErrFiles
      THEN
        errFiles[errIndex].wdw := wdw;
        MagicStrings.Assign (path, errFiles[errIndex].fname);
        MagicStrings.Append (name, errFiles[errIndex].fname);
        INC (errIndex);
      END;
    END;
  END;
  RETURN succ;
END OpenEditor;

PROCEDURE doHelp (wdw : INTEGER; kstate : BITSET);
VAR buf    : POINTER TO ARRAY [0..$7FFF] OF CHAR;
    bufLen : LONGCARD;
    str    : ARRAY [0..7] OF CHAR;
BEGIN
  IF CatEdit.IsEditTop (wdw) 
  THEN
    IF ~CatEdit.BlockIsMarked (wdw) 
    THEN
      CatEdit.MarkWord (wdw);
    END;
    IF ~CatEdit.BlockIsMarked (wdw) 
    THEN
      str := "FRED";
      SendHelp (str);
      RETURN
    END;
    IF CatEdit.GetBlock (wdw, FALSE, FALSE, buf, bufLen) THEN 
      SendHelp (buf^);
      DEALLOCATE (buf, 0);
    END;
  END;
END doHelp;

PROCEDURE menuMsgHdler (item, title : CARDINAL; kstate : BITSET);
VAR res    : INTEGER;
    z, z2  : CARDINAL;
    message: ARRAY[0..40] OF CHAR;
    wild   : ARRAY[0..6] OF CHAR;
    hdl    : INTEGER;
    font,
    size   : INTEGER;
    wdw    : INTEGER;
    edWdw  : INTEGER;
    fselTitle : ARRAY [0..49] OF CHAR;
    

  PROCEDURE handleFSelMessage (item : CARDINAL);
  BEGIN
    wild := allWild;
    Strings.Assign(OpenName, InSel, v.bool);
    IF item = Fredrsc.Open THEN message := 'Datei laden';
    ELSIF item = Fredrsc.Readfile THEN message := 'Datei hinzuladen';
    END;
    IF FselGet(InPath, InSel, wild, message, FALSE) THEN
      Strings.Assign(InSel, OpenName, v.bool);
      IF (item = Fredrsc.Open)
      THEN
        IF OpenEditor (InPath, InSel, edWdw, FALSE)
        THEN
        END;
      ELSIF item = Fredrsc.Readfile THEN
        CatEdit.EditMerge(wdw, InPath, InSel);
      END
    END
  END handleFSelMessage;

BEGIN
  wdw := WdwManager.theTopWindow;
  IF ~mouse THEN mtAppl.MouseOn; mouse := TRUE; END;
  CASE item OF
    Fredrsc.About     : DoAbout; |
    Fredrsc.Newfile   : IF CatEdit.OpenEditor ('','', TRUE, 
                                             FALSE, NIL, NIL, NIL, NIL, NIL, NIL, NIL, NIL,
                                             maxLineLength, TRUE, FALSE, -1, edWdw)
                      THEN
                      END; |
    Fredrsc.Readfile,
    Fredrsc.Open      : handleFSelMessage (item); |
    Fredrsc.Infofile  : doFileInfos(wdw);         |
    Fredrsc.Closewdw  : IF CatEdit.CloseEditor (wdw, FALSE)
                        THEN
                        END; |
    Fredrsc.Abandon   : CatEdit.EditAbandonText (wdw); |                    
    Fredrsc.Savefile  : CatEdit.EditSave (wdw,'','', FALSE);   |
    Fredrsc.Saveas    : IF CatEdit.BlockIsMarked (wdw)
                        THEN
                          Strings.Assign (blockSaveAs, fselTitle, v.bool);
                        ELSE 
                          Strings.Assign (saveAs, fselTitle, v.bool); 
                        END;
                        IF FselGet(SavePath, SaveName, allWild, fselTitle, FALSE) 
                        THEN
                          CatEdit.EditSave(wdw, SavePath, SaveName, TRUE)
                        END;  |
    Fredrsc.Callshel  : DoShell()|
    Fredrsc.Printit   : CatEdit.EditPrint (wdw, CatEdit.BlockIsMarked (wdw)); |
    Fredrsc.Quitprog  : IF autoSavePos THEN CatEdit.EditSavePos(); END;
                        quitProg := CatEdit.CloseAllEditors(FALSE); |
    Fredrsc.Doundo    : CatEdit.DoUndo (wdw); |
    Fredrsc.Markall   : CatEdit.MarkAll (wdw); |
    Fredrsc.Bstartbl  : CatEdit.SetBlockStart (wdw); |
    Fredrsc.Bblend    : CatEdit.SetBlockEnd (wdw); |
    Fredrsc.Bcut      : v.bool := CatEdit.EditCut (wdw); |
    Fredrsc.Bcopy     : v.bool := CatEdit.EditCopy (wdw); |
    Fredrsc.Bpaste    : CatEdit.EditPaste (wdw); |
    Fredrsc.Bmove     : CatEdit.IndentBlock (wdw); |
(*    Fredrsc.Bswitch   : CatEdit.BlockSwap (wdw); |
    Fredrsc.Bupper    : CatEdit.BlockUp (wdw); |
    Fredrsc.Blower    : CatEdit.BlockDown (wdw); |
    Fredrsc.Bcapital  : CatEdit.BlockCapitals (wdw) |
*)
    Fredrsc.Bfilter   : ProcessFilter (wdw, TRUE); |
    Fredrsc.Sfind     : DoSearchDialogue(wdw); |
    Fredrsc.Sagain    : SearchAgain (wdw, kstate); |
    Fredrsc.Sfindsel  : SearchBlock (wdw, kstate); |
    Fredrsc.Sreplace  : DoReplaceDialogue(wdw); |
    Fredrsc.Sragain   : ReplaceAgain (wdw,kstate); |
    Fredrsc.Sblstart  : CatEdit.ToBlockStart (wdw); |
    Fredrsc.Sblend    : CatEdit.ToBlockEnd (wdw); |
    Fredrsc.Ssetmark  : GetOrSetMark (FALSE, wdw); |
    Fredrsc.Stomark   : GetOrSetMark (TRUE, wdw);  |
    Fredrsc.Stoerr    : CatEdit.ShowError (wdw); |
    Fredrsc.Stoline   : GetLine (wdw); |
    Fredrsc.Nextwdw   : WdwManager.TopNextWindow (); |
    Fredrsc.Wstacked  : WdwManager.ArrangeWindows (WdwManager.STACKED) |
    Fredrsc.Wneben    : WdwManager.ArrangeWindows (WdwManager.BYSIDE) |
    Fredrsc.Wstaffel  : WdwManager.ArrangeWindows (WdwManager.OVERLAP) |
    Fredrsc.Wtiled    : WdwManager.ArrangeWindows (WdwManager.TILED) |
    Fredrsc.Ofontsel  : DoSelectFont (wdw); |
    Fredrsc.Ofkeys    : doFloskel (); |
    Fredrsc.Otabs     : GetTabSize (wdw); |
    Fredrsc.Oerrfile  : doErrorBox (); |
    Fredrsc.Otabmode  : CatEdit.ToggleMode (wdw, CatEdit.tabMode); WdwManager.FullRedrawWdw (wdw); |
    Fredrsc.Oumbruch  : GetRightMargin (wdw); |
    Fredrsc.Opaths    : PListHelp.SelectPaths(pathBox); |
    Fredrsc.Oshorti   : doShortBox(); |
    Fredrsc.Oprinter  : doPrinter(); |
    Fredrsc.Oinsert   : CatEdit.ToggleMode (wdw, CatEdit.insMode) |
    Fredrsc.Oindent   : CatEdit.ToggleMode (wdw, CatEdit.indentMode) |
    Fredrsc.Oautosav  : autoSavePos := ~autoSavePos; 
                        v.bool := ConfVars.SetConfigBool (cAutoSavePrefs, autoSavePos); |
    Fredrsc.Osaveins  : SavePrefs(); |
    Fredrsc.Pcompile,
    Fredrsc.Pcompend,
    Fredrsc.Pcomprun,
    Fredrsc.Pmake,
    Fredrsc.Pmakerun  : hdlComp (item, wdw) |
  ELSE
  END;
  MagicAES.MenuTnormal(menu, title, MagicAES.Set)
END menuMsgHdler;

(*----------------------------------------------*)
PROCEDURE clickHandler (x, y : INTEGER; Button: BITSET; Clicks: INTEGER; kstate : BITSET);
  VAR wdw   : INTEGER;
      res   : INTEGER;
      popStr: ARRAY [0..79] OF CHAR;
BEGIN
  IF (1 IN Button) & ~(0 IN Button)
  THEN
    WdwManager.ClickInWindow (x, y, wdw);
    IF wdw >= 0
    THEN
      IF CatEdit.IsEditTop (wdw)
       & ~CatEdit.GetMode (wdw, CatEdit.errorMode)
       & CatEdit.ClickIsInBlock (wdw, x, y)
       & (Clicks = 1)
      THEN
        (* Normaler Editor ist Top *)
        popStr := " Ausschneiden | Kopieren | Filtern... ";
        res := mtPopups.PosPopup (x, y, popStr, "");
        CASE res OF
          0: v.bool := CatEdit.EditCut (wdw); |
          1: v.bool := CatEdit.EditCopy (wdw); |
          2: ProcessFilter (wdw, FALSE); |
        ELSE
        END;
      END;
    END;
  END;
END clickHandler;


PROCEDURE keyHdler (scan, ch : CHAR; moKState : BITSET);
CONST
      helpScan     = 142C;
  VAR wdw : INTEGER;
      num : INTEGER;
      varName : ARRAY[0..20] OF CHAR;
      val     : ARRAY [0..511] OF CHAR;
      aktion,
      fname   : BOOLEAN;
      msg     : INTEGER;
BEGIN
  wdw := WdwManager.theTopWindow;
  IF (scan >= 73C) & (scan <= 104C) THEN
    (* F1 bis F10 *)
    IF ~mouse THEN
      mtAppl.MouseOn; mouse := TRUE;
    END;
    IF (moKState = {}) & CatEdit.IsEditTop (wdw)
    THEN
      num := ORD(scan) - 59 + 1;
      Strings.Assign (cNormalFkey, varName, v.bool);
      Strings.Append (StrConv.IntToStr (num,0), varName, v.bool);
      IF ConfVars.GetConfigString (varName, val)
      THEN
        v.bool := CatEdit.PutLine (WdwManager.theTopWindow, ADR(val), LENGTH (val));
      END;
    END;
  ELSIF (scan >= 124C) & (scan <= 135C)
  THEN
    (* Shift-F1 bis F10 *)
    IF CatEdit.IsEditTop (wdw) & 
       ~(MagicAES.KALT IN moKState) & 
        ~(MagicAES.KCTRL IN moKState)
    THEN
      (* mit Shift! *)
      num := ORD(scan) - 84 + 1;
      Strings.Assign (cShiftFkey, varName, v.bool);
      Strings.Append (StrConv.IntToStr (num,0), varName, v.bool);
      IF ConfVars.GetConfigString (varName, val)
      THEN
        v.bool := CatEdit.PutLine (WdwManager.theTopWindow, ADR(val), LENGTH (val));
      END;
    END;
  ELSIF (scan = helpScan)
  THEN
    doHelp (WdwManager.theTopWindow, moKState);
  ELSIF MagicAES.KCTRL IN moKState
  THEN
    (* Test auf Ctrl-1 bis Ctrl^7 auf dem Ziffernblock *)
    aktion := TRUE;
    fname  := FALSE;
    CASE scan OF 
    (*  147C: (* Num-7 *)
            msg := SEProto.ES_PROJECT; *)
      152C: (* Num-4 *)
            msg := SEProto.ES_MAKEALL;
    | 153C: (* Num-5 *)
            msg := SEProto.ES_EXEC;
            fname := TRUE;
    | 154C: (* Num-6 *)
            msg := SEProto.ES_MAKEEXEC;
    | 155C: (* Num-1 *)
            msg := SEProto.ES_COMPILE;
            fname := TRUE;
    | 156C: (* Num-2 *)
            msg := SEProto.ES_LINK;
            fname := TRUE;
    | 157C: (* Num-3 *)
            msg := SEProto.ES_MAKE;
    ELSE
      aktion := FALSE;
    END;
    IF aktion
    THEN
      IF fname 
      THEN
        (* Filenamen von TopWindow erfragen *)
        IF CatEdit.GetCompInfo (wdw, val, fname)
        THEN
          IF ~fname THEN 
            CatEdit.AskForSave (wdw);
          END;
          SendEsMessage (msg, ADR(val));
        END;
      ELSE
        SendEsMessage (msg, NIL);
      END;
    END;
  END;
END keyHdler;

PROCEDURE OnlyWildcards (name: ARRAY OF CHAR): BOOLEAN;
  VAR i, l : INTEGER;
BEGIN
  l := LENGTH (name);
  i := 0;
  WHILE i < l DO
    IF ~(name[i] IN CatTypes.charSet {'*','?','.'})
    THEN RETURN FALSE
    END;
    INC (i);
  END;
  RETURN TRUE;
END OnlyWildcards;

PROCEDURE msgHandler (buffAdr: ADDRESS; kstate: BITSET): BOOLEAN;
  VAR ch, scan : CHAR;
      moKState : BITSET;
      kReturn  : INTEGER;
      pName, pCmd : CatTypes.Str255Ptr;
      eMess: CatTypes.String255;
      path : CatTypes.pathStrType;
      name : CatTypes.nameStrType;
      suff : CatTypes.extStrType;
      access: SEProto.tPtrMessRec;
      errPtr: SEProto.tPtrErrInfo;
      errWdw: INTEGER;
      pBuff : POINTER TO ARRAY [0..9] OF INTEGER;
      handled: BOOLEAN;
BEGIN
  handled := TRUE;
  pBuff := buffAdr;
  CASE IsProtokoll(pBuff, kReturn, moKState, pName, pCmd) OF
    rNoproto : |
    rNone    : |
    rChar    : SplitWordToByte(kReturn, scan, char);
               IF MenuSearch(menu, mtAppl.ApplIdent, moKState, kReturn,
                             menuMsgHdler, ~mouse) THEN
                 mouse := TRUE;
                 event := event - {MagicAES.MUKEYBD}; (* kein Keyboard *)
               ELSE
                 keyHdler (scan, char, moKState);
               END; |
    (* Anderer Tastendruck wird evtl. �bergemangelt.. *)
    rText    : ; |
    rStart   : (*
               mtDir.SplitPath(pName^, path, name, suff);
               IF (pCmd # NIL) THEN
                 v.int := StartPrg(path, name, pCmd^, TRUE)
               ELSE
                 suff := '';
                 v.int := StartPrg(path, name, suff, TRUE)
               END *) |
    rOpen    : (* Entweder AV_OPENWIND oder VA_START. Bei VA_START ist pName NIL!,
                * und in pCmd steht eine Kommandozeile. Bei OpenWind steht in pName 
                * der Pfad und in pCmd ein Dateiname.
                *)
               IF pName # NIL
               THEN
                 (* AV_OPENWIND: Editor mit Datei ”ffnen *)
                 IF OnlyWildcards(pCmd^)
                 THEN
                   MagicStrings.Assign (pName^, InPath);
                   MagicStrings.Assign ('', InSel);
                   IF FselGet(InPath, InSel, '*.*', 'Datei laden', FALSE) 
                   THEN
                     Strings.Assign(InSel, OpenName, v.bool);
                     v.bool := OpenEditor (InPath, InSel, v.int, FALSE);
                   END;
                 ELSE
                   v.bool := OpenEditor (pName^, pCmd^, v.int, FALSE);
                 END;
               ELSE
                 (* VA_START: pCmd enth„lt Kommandozeile *)
                 IF MagicStrings.Length (pCmd^) > 0
                 THEN
                   (* Jetzt Kommandozeile auswerten: 
                    * entweder ist ein Dateiname enthalten oder sie f„ngt mit 
                    * - an und ist eine Kommandoliste
                    *)
                   IF CatEdit.FileIsEditor (pCmd^, errWdw)
                   THEN
                     WdwManager.TopWindow (errWdw);
                   ELSE
                     FileNames.SplitPath (pCmd^, InPath, OpenName);
                     v.bool := OpenEditor (InPath, OpenName, v.int, FALSE);
                   END;
                 END;
               END; |
    rSeMess  : access := buffAdr;
               CASE access^.msg OF
                 SEProto.SE_ERROR   : (* Fehler auswerten *)
                              WITH access^.errorPtr^ DO
                                IF errMess # NIL
                                THEN
                                  MagicStrings.Assign (errMess^, eMess);
                                ELSE
                                  MagicStrings.Assign ('Keine Fehlermeldung erhalten', eMess);
                                END;
                                IF errFile # NIL
                                THEN
                                  IF CatEdit.FileIsEditor (errFile^, errWdw)
                                  THEN
                                    WdwManager.TopWindow (errWdw);
                                    CatEdit.SetError (errWdw, errLine, errRow-1, eMess, TRUE);
                                  ELSE
                                    FileNames.SplitPath (errFile^, path, name);
                                    IF OpenEditor (path, name, errWdw, FALSE)
                                    THEN
                                      CatEdit.SetError (errWdw, errLine, errRow-1, eMess, TRUE);
                                    END;
                                  END;
                                END;
                              END; |
                 SEProto.SE_ERRFILE : 
                              WITH access^ DO
                                IF fnamePtr # NIL
                                THEN
                                  IF ~CatEdit.FileIsEditor (fnamePtr^, errWdw)
                                  THEN
                                    FileNames.SplitPath (fnamePtr^, path, name);
                                    v.bool := OpenEditor (path, name, errWdw, FALSE)
                                  END;
                                END;
                                IF errPtr # NIL
                                THEN
                                  FileNames.SplitPath (errPtr^, path, name);
                                  v.bool := OpenEditor (path, name, errWdw, TRUE)
                                END;
                              END; |
                 SEProto.SE_TERMINATE: (* Wir tun einfach so, als h„tten wir ein APTERM erhalten *)
                               pBuff^[0] := MagicAES.APTERM ; |
                 SEProto.SE_CLOSE:     
                               v.bool := CatEdit.CloseAllEditors(TRUE); |
               ELSE
               END;
  ELSE
    handled := FALSE;
  END;
  IF pBuff^[0] = MagicAES.MNSELECTED
  THEN
    event := event - {MagicAES.MUBUTTON}; (* keine Buttons *)
    menuMsgHdler(pBuff^[4], pBuff^[3], kstate);
    handled := TRUE;
  ELSIF pBuff^[0] = MagicAES.APTERM 
  THEN 
    quitProg := TRUE; 
    IF autoSavePos THEN CatEdit.EditSavePos(); END;
    v.bool := CatEdit.CloseAllEditors(TRUE);
    handled := TRUE;
  END;
  RETURN handled;
END msgHandler;

TYPE mSet = SET OF [0..255];

VAR menuSet : mSet;

PROCEDURE enableMenuItems();

  PROCEDURE EnableItem (tree : ADDRESS; item : INTEGER; enable : BOOLEAN);
  BEGIN
    IF enable
    THEN
      IF ~(item IN menuSet) THEN 
        MagicAES.MenuIenable (menu, item, 1); 
        INCL(menuSet, item);
      END;
    ELSE
      IF item IN menuSet THEN 
        MagicAES.MenuIenable (menu, item, 0); 
        EXCL(menuSet, item);
      END;
    END;
  END EnableItem;

  PROCEDURE CheckItem (tree : ADDRESS; item : INTEGER; enable : BOOLEAN);
  BEGIN
    IF enable
    THEN
      MagicAES.MenuIcheck (menu, item, 1);
    ELSE
      MagicAES.MenuIcheck (menu, item, 0);
    END;
  END CheckItem;

  VAR wdw : INTEGER;
      bl,
      isTop,
      moreWinds,
      twoWinds : BOOLEAN;
BEGIN
  wdw := WdwManager.theTopWindow;
  bl := CatEdit.BlockIsMarked (wdw);
  isTop := CatEdit.IsEditTop (wdw);
  moreWinds := WdwManager.TopNextPossible(); 
  twoWinds := WdwManager.TopNextPossible();

  EnableItem (menu, Fredrsc.Readfile, isTop);    (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Infofile, isTop);    (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Closewdw, isTop);    (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Abandon , isTop);    (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Savefile, isTop);    (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Saveas  , isTop);    (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Printit , isTop);    (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Markall , isTop);    (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Bstartbl, isTop);    (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Bblend  , isTop);    (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Bcut    , bl);       (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Bcopy   , bl);       (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Bpaste  , isTop);    (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Bmove   , bl);       (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Bfilter , bl);       (* STRING in Baum MENU *)

  EnableItem (menu, Fredrsc.Sfind   , isTop);    (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Sagain  , isTop & searchOpts.isSet);    (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Sreplace, isTop);    (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Sfindsel, isTop);    (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Sragain , isTop & replaceOpts.isSet);    (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Sblstart, bl);       (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Sblend  , bl);       (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Ssetmark, isTop);    (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Stomark , isTop);    (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Stoline , isTop);    (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Stoerr  , isTop);    (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Nextwdw , moreWinds);   (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Wstacked, twoWinds);    (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Wneben  , twoWinds);    (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Wstaffel, twoWinds);    (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Wtiled  , twoWinds);    (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Ofontsel, isTop);       (* STRING in Baum MENU *)
  (*
  EnableItem (menu, Fredrsc.Otabs   , isTop);       (* STRING in Baum MENU *)
  *)

  EnableItem (menu, Fredrsc.Oumbruch, isTop);      (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Otabmode, isTop);      (* STRING in Baum MENU *)
  (*
  EnableItem (menu, Fredrsc.Obackup , isTop);      (* STRING in Baum MENU *)
  *)
  EnableItem (menu, Fredrsc.Oinsert , isTop);      (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Oindent , isTop);      (* STRING in Baum MENU *)
  IF isTop
  THEN
    CheckItem (menu, Fredrsc.Otabmode, CatEdit.GetMode(wdw, CatEdit.tabMode));         (* STRING in Baum MENU *)
    (*
    CheckItem (menu, Fredrsc.Obackup , CatEdit.GetMode(wdw, CatEdit.autoBackup));      (* STRING in Baum MENU *)
    *)
    CheckItem (menu, Fredrsc.Oinsert , CatEdit.GetMode(wdw, CatEdit.insMode));         (* STRING in Baum MENU *)
    CheckItem (menu, Fredrsc.Oindent , CatEdit.GetMode(wdw, CatEdit.indentMode));      (* STRING in Baum MENU *)
  END;
  
  EnableItem (menu, Fredrsc.Pcompile, isTop & (mm2shell OR SEProtoActiv ()));    (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Pcompend, isTop);    (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Pcomprun, isTop);    (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Pmake   , isTop);    (* STRING in Baum MENU *)
  EnableItem (menu, Fredrsc.Pmakerun, isTop);    (* STRING in Baum MENU *)

  CheckItem (menu, Fredrsc.Oautosav , autoSavePos);(* STRING in Baum MENU *)
END enableMenuItems;

VAR crash : BOOLEAN;

(* Hier kommt jetzt der Crash-Handler *)
PROCEDURE crashHandler;
  (* Wird automatisch bei Terminierung des Programms aufgerufen *)
  VAR entry : CatTypes.Str255Ptr;
BEGIN
  IF MOSCtrl.ModLevel # 1
  THEN
    (* Pfadliste l”schen *)
    Lists.ResetList (ShellMsg.SrcPaths);
    entry := Lists.NextEntry (ShellMsg.SrcPaths);
    WHILE entry # NIL DO
      Lists.RemoveEntry (ShellMsg.SrcPaths,v.bool);
      DEALLOCATE (entry, 0);
      entry := Lists.NextEntry (ShellMsg.SrcPaths);
    END;
    ShellMsg.SrcPaths := oldSrcPaths;
  END;
  mtAppl.MouseOn();
  v.int := MagicAES.MenuBar(menu, MagicAES.Reset);
  v.bool := CatEdit.CloseAllEditors(FALSE);
  MagicAES.RsrcFree();
  SendTerminate();
  MagicAES.WindUpdate(MagicAES.ENDUPDATE);
  mtAppl.ApplTerm(termCode); 
END crashHandler;

PROCEDURE isFilename (REF s : ARRAY OF CHAR): BOOLEAN;
  VAR p,f :ARRAY [0..139] OF CHAR;
      i : INTEGER;
BEGIN
  i := 0;
  i := Strings.Pos ('.',s,0);
  IF i > 0 THEN RETURN TRUE END;
  i := Strings.Pos ('\',s,0);
  IF i > 0 THEN RETURN TRUE END;
  i := Strings.Pos (':',s,0);
  IF i > 0 THEN RETURN TRUE END;
  RETURN FALSE
END isFilename;

PROCEDURE isNumber (REF s : ARRAY OF CHAR):BOOLEAN;
  VAR i : LONGINT;
      j : CARDINAL;
BEGIN
  j := 0;
  i := StrConv.StrToLInt(s,j,v.bool);
  RETURN v.bool
END isNumber;

VAR stck: MemArea;
    rHdl: TermCarrier;
    resName : ARRAY [0..79] OF CHAR;
    wdw : INTEGER; 
    eLine : LONGINT;
    eRow  : INTEGER;
    eMsg  : ARRAY [0..79] OF CHAR;
    fullName,
    path,
    name,
    para  : ARRAY [0..139] OF CHAR;
    firstNumber,
    allSet,
    numberRead : BOOLEAN;
    p          : CARDINAL;
    i, 
    params     : INTEGER;
    topVdi     : INTEGER;
    
    multiTasking : BOOLEAN;
    multiTOS     : BOOLEAN;
    magixCookie  : magixCookiePtr;
    isMagiX      : BOOLEAN;
    started      : BOOLEAN;
    otherId      : INTEGER;
    apName       : PtrMaxStr;

PROCEDURE FindOtherFred (VAR otherId : INTEGER) : BOOLEAN;
  VAR appName : MaxStr;
      i       : INTEGER;
BEGIN
(*
  IF isMagiX
  THEN
  
    Strings.Assign ('fred.prg', appName, v.bool);
    otherId := MagicAES.ApplFind (ADR(appName));
    IF otherId = mtAppl.ApplIdent
    THEN
      appName[0] := '?';
      appName[1] := 0C;
      appName[3] := 0C;
      FOR i := otherId+1 TO MagicAES.AESGlobal.apCount-1 DO
        appName[2] := CHR(i);
        IF (MagicAES.ApplFind (ADR(appName)) # 0) & 
            Strings.StrEqual ('FRED.PRG', appName)
        THEN
          RETURN TRUE
        END;
      END;
    ELSE
      RETURN TRUE
    END;
  ELSE
  *)
    (* MultiTOS *)
    FOR i := 0 TO 12 DO appName[i] := 0C; END;
    IF MagicAES.ApplSearch (MagicAES.APFIRST, appName, v.int, otherId)
    THEN
      REPEAT 
        Strings.DelTrailingBlanks (appName);
        IF (otherId # mtAppl.ApplIdent) & 
            Strings.StrEqual(appName, 'FRED')
        THEN
          RETURN TRUE
        END;
        FOR i := 0 TO 12 DO appName[i] := 0C; END;
      UNTIL ~MagicAES.ApplSearch (MagicAES.APNEXT, appName, v.int, otherId);
    END;
(*  END; *)
  RETURN FALSE;
END FindOtherFred;

(*$L-,R-,S-*)
PROCEDURE sigHandler();
BEGIN
  ASSEMBLER
    MOVE.W  #0,termCode
    MOVE.W  #TRUE,quitProg
  END;
END sigHandler;
(*$L=,R=,S=*)

PROCEDURE installSignalHandler();
BEGIN
  IF MintUtil.IsMiNT()
  THEN
    (* Folgende Signale werden abgefangen und ignoriert:
     * SIGHUP, SIGINT, SIGSYS, 
     *)
    v.lbset := Mintbind.Psigblock (MagicSys.lBITSET{Mintbind.SIGHUP, Mintbind.SIGINT, Mintbind.SIGSYS});
    (* Folgende Signale werden mit Programmterminierung befolgt:
     * SIGQUIT, SIGPIPE, SIGTERM, SIGXCPU
     * Dabei ist es mir egal, ob die Installation geklappt hat oder nicht.
     *)
    v.a := Mintbind.Psignal (Mintbind.SIGTERM, ADDRESS (sigHandler));
    v.a := Mintbind.Psignal (Mintbind.SIGQUIT, ADDRESS (sigHandler));
    v.a := Mintbind.Psignal (Mintbind.SIGPIPE, ADDRESS (sigHandler));
    v.a := Mintbind.Psignal (Mintbind.SIGXCPU, ADDRESS (sigHandler));
  END;
END installSignalHandler;

PROCEDURE handleEvents ();
BEGIN
  ClearBuffer(event, FALSE, moKState, ORD(SCAN), CH);

  IF MagicAES.MUKEYBD IN event THEN (* Keyboard - MenuKommandos*)
    IF MenuSearch(menu, mtAppl.ApplIdent, moKState, kReturn,
                  menuMsgHdler, ~mouse) THEN
      mouse := TRUE; (* Wird dann in MenuSearch gemacht *)
      event := event - {MagicAES.MUKEYBD}; (* kein Keyboard *)
    END;
  END;
  IF MagicAES.MUBUTTON IN event
  THEN
    IF ~mouse THEN
      mtAppl.MouseOn; mouse := TRUE; (*
      MagicAES.GrafMouse(MagicAES.MON, NIL); mouse := TRUE *)
    END;
    (* Warten auf loslassen oder waitingTime *)
    e := MagicAES.EvntMulti(
               {MagicAES.MUBUTTON, MagicAES.MUTIMER},
                0,{1,0},{}, 0,dr, 0,dr, mess, 100, 0,
                v.int, v.int, v.bset, v.int, v.bset, v.int, v.char, v.int);
  END;
  IF WdwManager.HandleEvent (event, mess, moButton, moKState, char, scan, kReturn, moX, moY, bReturn)
  THEN
  END;
  IF MagicAES.MUMESAG IN event THEN
    v.bool := msgHandler (ADR(mess), moKState);
    event := event - {MagicAES.MUBUTTON};
    (* nicht gleichzeitig Button und Message! *)
  END;

  IF MagicAES.MUM1 IN event THEN
    IF ~mouse THEN
      mtAppl.MouseOn; mouse := TRUE;
    END;
  END;

  IF MagicAES.MUBUTTON IN event THEN (* Button *)
    clickHandler (moX, moY, moButton, bReturn, moKState);
  END;

  IF MagicAES.MUKEYBD IN event THEN (* Keyboard - kann eigentlich nur noch F-Taste sein *)
    keyHdler (scan, char, moKState);
  END;
END handleEvents;

PROCEDURE handlePendingEvents();
  VAR etv : BITSET;
BEGIN
  REPEAT
    event := MagicAES.EvntMulti(
                   {MagicAES.MUMESAG, MagicAES.MUTIMER},
                    0, {},{}, 0, dr, 0, dr, mess, 50, 0,
                    v.int, v.int, v.bset, v.int, v.bset, v.int, v.char, v.int);
    etv := event;
    IF MagicAES.MUMESAG IN event
    THEN
      MagicAES.WindUpdate(MagicAES.BEGUPDATE);
      handleEvents();
      MagicAES.WindUpdate(MagicAES.ENDUPDATE);
    END;
  UNTIL ~(MagicAES.MUMESAG IN etv);
END handlePendingEvents;

BEGIN
  CatGlobal.isMintDomain := Mintbind.Pdomain (1) = 0;
  filterNumber := 0;
  shortFileRead := FALSE;
  searchOpts.isSet := FALSE;
  replaceOpts.isSet := FALSE;
  installSignalHandler();
  CatchProcessTerm (rHdl, crashHandler, stck);

(* Hier kann man sich ein:  mtAppl.ApplInit(); denken   *)
(* Es wird automatisch ausgef�hrt..                     *)

  errIndex := 0;

  mtAppl.MouseBusy;
  termCode := 0;
  mm2shell :=  MOSCtrl.ModLevel # 1;
  multiTasking := MagicAES.AESGlobal.apCount # 1;
  isMagiX := FALSE;
  multiTOS := (MagicAES.AESGlobal.apVersion >= $400)
            & multiTasking;
  IF MagicCookie.FindCookie ('MagX', magixCookie)
  THEN
    isMagiX := magixCookie^.aesVars # ADDRESS(0L);
  END;
  resName := 'fred.rsc';
  IF InitResource (resName)
  THEN
    menuSet := mSet {0..255};
    shellCommand := "";
    
    ConfVars.GetConfDefBool (cAutoSavePrefs, autoSavePos, FALSE);

    mtAlerts.ConfigAlert (mtAlerts.alticon);

    MagicAES.WindUpdate(MagicAES.BEGUPDATE);
    IF multiTOS THEN 
      apName := CADR (eddixName);
      v.int := MagicAES.MenuRegister (mtAppl.ApplIdent, apName^);
      (* Und auch Bescheid sagen, daž wir AP_TERM verstehen *)
      v.int := MagicAES.ShelWrite (MagicAES.InformAES, INTEGER(BITSET{MagicAES.ApTermBit}), 0, "", "");
    END;
    v.int := MagicAES.MenuBar(menu, MagicAES.Set);    (* show our menubar   *)
    
    mtDials.DialConfig (mtDials.UseConfig, FALSE);

(* ---------------------------------------------------------------------- *)

    (* Parameter holen und auswerten *)
    firstNumber := TRUE;
    numberRead := FALSE;
    allSet := FALSE;
    wdw := -1;
    params := mtCommand.ParamCount();
    i := 1;
    eMsg := "";
    started := FALSE;
    WHILE params > 0 DO 
      mtCommand.ParamString (i,para);
      IF isFilename (para)
      THEN
        Strings.Assign (para, fullName, v.bool);
        FileNames.SplitPath (fullName, path, name);
        IF multiTasking & FindOtherFred (otherId)
        THEN
          SendOpenwind (otherId, ADR(path), ADR(name));
          MagicAES.WindUpdate (MagicAES.ENDUPDATE);
          started := FALSE;
          REPEAT
            event := MagicAES.EvntMulti(
                     {MagicAES.MUTIMER, MagicAES.MUMESAG},
                      0, {0},{0}, MagicAES.LeaveRect, mrect, 0,dr, mess, 500, 0,
                      moX, moY, moButton, kReturn, moKState, SCAN, CH, bReturn);
            (* Timeout 500 ms *)
            IF (MagicAES.MUMESAG IN event) & 
               (mess[0] = 4721H) (* VA_WINDOPEN *)
            THEN
              started := started OR (mess[3] # 0);
            END;
          UNTIL {MagicAES.MUTIMER} = event;
          MagicAES.WindUpdate (MagicAES.BEGUPDATE);
        ELSE
          started := FALSE;
        END;
        IF ~started & OpenEditor (path, name, wdw, FALSE)
        THEN
          Strings.Assign (path, InPath, v.bool);
        END;
      ELSIF isNumber (para)
      THEN
        IF firstNumber 
        THEN
          p := 0;
          eLine := StrConv.StrToLInt (para, p, v.bool);
          firstNumber := FALSE;
        ELSE
          p := 0;
          eRow := StrConv.StrToInt (para, p, v.bool);
          numberRead := TRUE;
        END;
      ELSE
        (* Muž Fehlermeldung sein *)
        Strings.Assign (para, eMsg, v.bool);
        IF Strings.Pos ('"',eMsg,0) >= 0
        THEN
          (* Stringanfang oder Ende in Parameter *)
          REPEAT
            Strings.Append (' ',eMsg, v.bool);
            INC (i);
            DEC (params);
            mtCommand.ParamString (i, para);
            Strings.Append (para, eMsg, v.bool);
          UNTIL (params = 0) OR (Strings.Pos ('"',para,0)>=0)
        END;
        IF numberRead & (wdw > 0)
        THEN
          CatEdit.SetError (wdw, eLine, eRow, eMsg, TRUE);
          firstNumber := TRUE;
          numberRead := FALSE;
        ELSIF ~firstNumber & (wdw > 0)
        THEN
          CatEdit.SetError (wdw, eLine, 0, eMsg, TRUE);
          allSet := TRUE;
          firstNumber := TRUE;
        ELSIF (wdw > 0)
        THEN
          CatEdit.SetError (wdw, 1, 0, eMsg, TRUE);
        END;
      END;
      INC (i);
      DEC(params);
    END;
    IF started 
    THEN
      TermProcess (0);
    END;
    IF ~firstNumber OR numberRead
    THEN
      IF numberRead 
      THEN
        CatEdit.SetError (wdw, eLine, eRow, eMsg, TRUE);
      ELSE
        CatEdit.SetError (wdw, eLine, 0, eMsg, TRUE);
      END;
    END;
    CatEdit.EditRestorePos ();

    IF ConfVars.GetConfigString (cShortFile, lastShort)
    THEN
      CatEdit.ReadShortkeyFile (lastShort);
      shortFileRead := TRUE;
    END;
  
    ConfVars.GetConfDefStr (cErrMask, errMask, '');

    IF MagicCookie.FindCookie (magicPCCookie, v.lcard) 
    (* Jetzt k”nnen wir endlich normal weitermachen *)
    THEN
      ConfVars.GetConfDefBool (cMagicPCKeys, v.bool, TRUE);
      IF v.bool
      THEN
        WdwManager.SetMagicPCKeyTranslation (TRUE);
      END;
    END;

    (* XACC initialisieren *)
    MagicAES.WindUpdate(MagicAES.ENDUPDATE); (* wg. sofort wieder aus.. *)
    ProtoInit();

    handlePendingEvents();    (* Events behandeln *)

    (* SE-Protokoll initialisieren *)
    SeProtoInit();

    handlePendingEvents();    (* Events behandeln! *)

    WdwManager.InstallGlobalMenu (menu, msgHandler);

    MagicAES.WindUpdate(MagicAES.BEGUPDATE); (* wg. sofort wieder aus.. *)

    mtAppl.MouseArrow;
    mouse := TRUE;
    WITH mrect DO
      x := 0; y := 0; w := 1; h := 1;
    END;
    
    WHILE ~quitProg DO
    
      enableMenuItems();

      MagicAES.WindUpdate(MagicAES.ENDUPDATE);

      IF PendingKey()
      THEN
        event := {MagicAES.MUKEYBD};
        PopKey(moKState, scan, char);
      ELSE
        IF mouse
        THEN
          event := MagicAES.EvntMulti(
                   {MagicAES.MUKEYBD, MagicAES.MUBUTTON, MagicAES.MUMESAG, MagicAES.MUTIMER},
                    259, {1,0},{}, MagicAES.LeaveRect, mrect, 0,dr, mess, 350,0,
                    moX, moY, moButton, kReturn, moKState, SCAN, CH, bReturn);
  
        ELSE
          event := MagicAES.EvntMulti(
                   {MagicAES.MUKEYBD, MagicAES.MUBUTTON, MagicAES.MUM1, MagicAES.MUMESAG, MagicAES.MUTIMER},
                    259, {1,0},{}, MagicAES.LeaveRect, mrect, 0,dr, mess, 350,0,
                    moX, moY, moButton, kReturn, moKState, SCAN, CH, bReturn);
        END;
        WITH mrect DO
          x := moX; y := moY;
        END;
        SplitWordToByte(kReturn, scan, char);
      END;
      
      MagicAES.WindUpdate(MagicAES.BEGUPDATE);
      
      handleEvents();

    END; (* WHILE ~quitProg *)


(* ---------------------------------------------------------------------- *)

    IF autoSavePos THEN SavePrefs() END;
  ELSE
    SendTerminate();
  END;
  TermProcess (termCode);
END Fred.
